** SQLite
=> WebBrowser, Android, iOS 기기 등에 내장된 관계형 데이터베이스 (테이블)
=> 외부기기에서는 접근이 불가능한 데이터베이스
=> 응용 프로그램의 부분저긴 모듈로 동작
=> Mac OS X에소 설치되어 있고 Python에도 설치가 되어 있다.
=> SQL은 MySQL과 거의 유사
1. Xcode에서 SQLite 사용
=> Xcode에서 SQLite를 사용할려면 libsqlite 라이브러리가 필요
Project에서 Build Phases 탭에서 Link Binary with Libraries영역에서 추가
=> sqlite 는 C++라이브러리로 만들어져 있다.
대부분의 경우 C++로 직접 사용하지 않고 Objective-C로 래핑된 FMDB와 같은 외부 라이브러리를 이용한다.
Swift 프로젝트에 FMDB 라이브러리를 추가하면 Swift 문법으로 사용할 수 있도록 Bridge Header 파일을 생성해 주어야 한다.
2. sqlite를 직접 편집
=> 여러가지 편집 프로그램이 있다.
http://sqlitebrowser.org 같은 곳에서 제공
dbeaver는 만들어져 있으면 접속은 가능한데 파일을 생성하지는 못한다.
3. FMDB 사용
=> SQLite를 Objective-C로 사용할 수 있도록 래핑한 라이브러리
1) 주요 클래스
FMDatabase : SQL 실행 클래스
FMResultSet : select 구문의 결과를 저장하기 위한 클래스
FMDatabaseQueue : 다중 스레드로 사용하기 위한 클래스
2) 데이터베이스 생성 및 열기
=> 생성은 FMDatabase(path: 파일 경로)
=> 열기는 open() 메소드 호출
3) SQL 실행
=> FMDatabase 객체를 가지고 executeStatements(sql문장) 또는 executeQuery(sql문장, withArguments: 배열)
4) 닫기
=> close()
** 연락처 테이블을 생성해서 전체보기, 삽입, 삭제를 구현 SQLite3 이용
1. 프로젝트를 생성 - PhoneBook
2. SQLite3 라이브러리를 추가
3. FMDB 라이브러리를 다운로드 받아서 프로젝트에 복사
=> 다운로드 받을 주소 : https://github.com/ccgus/fmdb.git - [Source Control] - [Clone]을 선택하고 URL을 입력하고 Clone을 클릭
=> 브릿지 헤더 생성하고 작성 : C++이나 Objective-C로 만들어진 내용을 Swift에서 사용할 수 있도록 해주는 파일
![]() |
![]() 폴더를 새로 만들고 복사 |
=> 생성된 브릿지 헤더 파일에 작성
#import "FMDB.h"
4. 첫번째 화면을 테이블 뷰 컨트롤러를 만들고 네에게이션 바를 추가
1) UITableViewController로 부터 상속받는 클래스를 생성
2) 스토리보드에 TableViewController를 추가하고 Class 속성과 StoryboardID 속성을 수정
=> 첫번째 뷰 컨트롤러가 되어야하는 경우에는 is Initial View Controller 속성을 체크
3) TableViewController에 NavigationController를 추가 [Editor] - [Embed in] - [NavigationController]
5. 데이터를 저자할 파일과 테이블을 생성
=> 한 번만 생성 : AppDelegate에서 하는 것이 효율적
=> 파일의 존재 여부를 확인해서 없으면 파일을 만들고 있으면 새로 생성할 필요 없다.
=> AppDelegate.swift 파일의 앱이 실행될 때 호출되는 메소드
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
//앱이 실행될 때 호출되는 메소드
//launchOptions 에 앱이 실행된 방법을 저장
//앱은 직접 실행할 수도 있지만 URL을 이용해서 실행할 수도 있다.
//URL을 이용해서 실행하는 방법이 웹에서 페이스북을 보려고 할 때 앱으로 실행하시겠습니까 물어보고 실행하는 것이나 카카오톡에서 다른 게임이나 앱을 실행할 때 사용한다.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
//파일 경로를 생성 - Document 디렉토리의 phonebook.sqlite
let fileMgr = FileManager.default
//도큐먼트 디렉토리 경로 만들기
let docPaths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let docDir = docPaths[0] as String
//파일경로 생성
let dbPath = docDir.appending("/phonebook.sqlite")
//파일의 존재 여부 확인
if fileMgr.fileExists(atPath: dbPath){
NSLog("파일이 존재함")
}else{
//데이터 베이스 생성
let contactDB = FMDatabase(path: dbPath)
//데이터베이스 열기
if contactDB.open(){
let sql =
"""
create table if not exists phonebook(num INTEGER not null primary key autoincrement,
name TEXT, phone TEXT, addr TEXT)
"""
if contactDB.executeStatements(sql){
NSLog("테이블 생성 성공")
}else{
NSLog("테이블 생성 실패")
}
}else{
NSLog("데이터베이스 열기 실패")
}
}
return true
}
6. DTO & DAO 패턴
=> DTO(Data Transfer Object) : 여러 개의 데이터를 다른 곳에서 사용하고자 할 때 하나로 묶어서 전송하기 위해서 만드는 클래스 또는 객체
일반적인 언어는 클래스로 생성
Swift는 클래스(Class), 구조체(Struct - 값들의 집합, 튜플(값의 모임)
튜플로 만들 때는 (자료형 나열)로 자료형을 만들고 실제 객체를 만들 때는 값을 나열
=>튜플로 DTO 만들기
typealias 자료형이름 = (각 데이터의 자료형을 나열)
=> 튜플 객체 만들기
(자료형에 맞는 데이터 나열)
=> DAO(Data Access Object) : 데이터와 관련된 작업을 모아놓은 클래스 또는 객체
=> 작업을 할 때 서비스 단위로 작업을 하기도 하고 클래스 단위로 작업을 하기도 한다.
=> 서버 애플리케이션을 만들 때 클래스 단위로 작업을 한다면 단위 테스트는 필수이다.
7. DAO 클래스 생성 - 전체 데이터 가져오기, 기본키를 가지고 하나의 데이터 찾아오기, 삽입, 삭제하기 - PhonebookDAO
//
// PhoneBookDAO.swift
// PhoneBook
//
// Created by Lee Seungbum on 2020/09/08.
// Copyright © 2020 Lee Seungbum. All rights reserved.
//
import Foundation
import UIKit
class PhoneBookDAO{
//DTO 생성
typealias PhoneRecord = (Int, String, String, String)
//지연 생성(클라이언트에서 주로 이용)을 이용한 데이터베이스 연결
//처음에는 존재하지 않다가 처음 사용할 때 구문을 수행해서 생성
lazy var fmdb : FMDatabase! = {
//데이터베이스 파일 경로 가져오기
let fileMgr = FileManager.default
let docPaths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let docDir = docPaths[0] as String
let dbPath = docDir.appending("/phonebook.sqlite")
//데이터베이스 연결
let db = FMDatabase(path: dbPath)
return db
}()
//서버프로그래밍에서는 하나의 요청이 오면 데이터베이스를 열고 작업을 수행한 후 닫는다.
//이 작업을 직접하지는 않고 Connection Pool을 이용해서 수행
//클라이언트 프로그래밍에서는 이럴 필요가 없다.
//시작할 때 연결하고 종료할 때 닫는 방식을 이용한다.
//초기화 메소드 - 생성자
init(){
//데이터베이스 열기
self.fmdb.open()
}
//소멸자
deinit {
self.fmdb.close()
}
//전체 데이터 가져오는 메소드
//매개변수가 없고 데이터의 모임을 리턴
func find() -> [PhoneRecord]{
//결과를 저장할 List를 생성
//출력하는 곳에서는 반복문을 수행하기 때문에 nil이 리턴되면 안된다.
var phoneList = [PhoneRecord]()
//SQL 생성
let sql = "select num,name,phone,addr from phonebook order by num asc"
//2. 실행
let rs = try! self.fmdb.executeQuery(sql, values: nil)
//3. 결과 사용
while rs.next(){
let num = rs.int(forColumn: "num")
let name = rs.string(forColumn: "name")
let phone = rs.string(forColumn: "phone")
let addr = rs.string(forColumn: "addr")
phoneList.append((Int(num), name!, phone!, addr!))
}
//결과 리턴
return phoneList
}
//num을 받아서 하나의 데이터를 리턴하는 메소드 - 상세보기
func get(num:Int) -> PhoneRecord?{
//1.sql 생성
let sql = "select num, name, phone, addr from phonebook where num = ?"
//2.SQL 실행
let rs = self.fmdb.executeQuery(sql, withArgumentsIn:[num])
//3.결과가 있는지 확인
if let _rs = rs{
_rs.next()
let num = _rs.int(forColumn: "num")
let name = _rs.string(forColumn: "name")
let phone = _rs.string(forColumn: "phone")
let addr = _rs.string(forColumn: "addr")
return (Int(num), name!, phone!, addr!)
}else{
return nil
}
}
//데이터를 삽입하는 메소드
func create(name:String!, phone:String!, addr:String!) -> Bool {
do{
//sql 생성
let sql = "insert into phonebook(name, phone, addr) values(?,?,?)"
//SQL 실행
try self.fmdb.executeUpdate(sql, values: [name!, phone!, addr!])
return true
}catch let error as NSError{
NSLog(error.localizedDescription)
return false
}
}
//데이터를 삽입하는 메소드
func delete(num:Int) -> Bool {
do{
//sql 생성
let sql = "delete from phonebook where num=?"
//SQL 실행
try self.fmdb.executeUpdate(sql, values: [num])
return true
}catch let error as NSError{
NSLog(error.localizedDescription)
return false
}
}
}
8. PhoneListVC.swift 파일에 전체 데이터 가져오기 구현
1) 2개의 인스턴스를 선언 - 출력할 데이터를 저장하는 배열, DAO
import UIKit
class PhoneListVC: UITableViewController {
//데이터 목록을 저장할 변수
var phoneBook : [(num:Int, name:String, phone:String, addr:String)]!
//DAO 변수
let dao = PhoneBookDAO()
2) viewDidLoad 메소드에 전체 데이터를 가져오고 UI를 초기화하는 코드를 추가
override func viewDidLoad() {
super.viewDidLoad()
//전체 데이터 가져오기
phoneBook = self.dao.find()
//네비게이션 바에 레이블 출력
//새로 생성해서 추가
let navTitle = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 60))
navTitle.numberOfLines = 2
navTitle.textAlignment = .center
navTitle.text = "연락처 목록 \n" + "총\(self.phoneBook.count) 개"
self.navigationItem.titleView = navTitle
}
9.PhoneListVC.swift 파일에 테이블 뷰 출력을 위한 메소드 재정의
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return phoneBook.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//출력할 데이터를 찾아오기
let rowData = phoneBook[indexPath.row]
//셀을 생성
let cellIdentifier = "Cell"
var cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier)
if cell == nil{
cell = UITableViewCell(style:.subtitle, reuseIdentifier:cellIdentifier)
}
cell!.textLabel!.text = rowData.name
cell!.detailTextLabel!.text = "\(rowData.phone) \(rowData.addr)"
return cell!
}
10.데이터 추가 기능
=>네비게이션 바의 오른쪽에 바 버튼 아이템을 배치해서 아이템을 클릭하면 대화상자를 출력하고 대화상자에 입력하고 확인을 누르면 테이블에 데이터를 추가하도록 생성
1)바버튼 아이템이 호출할 메소드 생성 - add
//바버튼 아이템이 호출할 메소드
@objc func add(_ sender:Any){
//대화상자 만들기
let alert = UIAlertController(title:"데이터 삽입", message:"연락처 등록", preferredStyle:.alert)
//입력 필드 만들기
alert.addTextField(){(tf) in tf.placeholder="이름"}
alert.addTextField(){(tf) in tf.placeholder="전화번호"}
alert.addTextField(){(tf) in tf.placeholder="주소"}
//버튼 만들기
alert.addAction(UIAlertAction(title:"취소", style:.cancel))
alert.addAction(UIAlertAction(title:"확인", style:.default){(_) in
//입력한 내용 가져오기
let name = alert.textFields?[0].text
let phone = alert.textFields?[1].text
let addr = alert.textFields?[2].text
//테이블에 삽입
self.dao.create(name:name, phone:phone, addr:addr)
//데이터를 다시 가져와서 재출력
self.phoneBook = self.dao.find()
self.tableView.reloadData()
//레이블도 다시 출력
let naviTitle = self.navigationItem.titleView as! UILabel
naviTitle.text = "연락처 목록\n" + "총 \(self.phoneBook.count) 개"
})
//대화상자 출력
self.present(alert, animated:true)
}
2)viewDidLoad 메소드에 바버튼 아이템을 배치 - add 라는 메소드를 호출하도록 생성
//네비게이션 바의 오른쪽 바 버튼 아이템 추가
self.navigationItem.rightBarButtonItem =
UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(add(_:)))
11.데이터 삭제 구현
=>네비게이션 바의 왼쪽에 편집 버튼을 두고 편집 버튼을 누르면 삭제 버튼이 보이도록 하고 삭제를 누르면 실제 데이터 삭제
1)viewDidLoad 메소드에 네비게이션 바의 왼쪽에 편집 버튼 배치
//왼쪽에 편집 버튼 배치
self.navigationItem.leftBarButtonItem = self.editButtonItem
self.tableView.allowsSelectionDuringEditing = true
2) edit 버튼을 눌렀을 때 보여질 버튼의 종류를 설정하는 메소드 재정의
//edit 버튼을 눌렀을 때 보여질 버튼 설정 메소드
override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle{
.delete
}
3) 삭제를 누를 때 호출되는 메소드 재정의
//실제 삭제를 눌렀을 때 호출되는 메소드
override func tableView(_ tableView:UITableView, commit editingStyle:UITableViewCell.EditingStyle, forRowAt indexPath:IndexPath){
let num = self.phoneBook[indexPath.row].num
dao.delete(num:num)
//삭제하는 애니메이션을 적용
self.phoneBook.remove(at: indexPath.row)
tableView.deleteRows(at:[indexPath], with:.fade)
}
** In Memory DB
=> 데이터베이스의 내용은 보조 기억 장치에 존재
=> 데이터베이스에서 내용을 가져올 때는 보조 기억 장치에서 가져오기 때문에 속도가 느리다.
=> 데이터베이스의 내용을 보조 기억장치에 저장하지 않고 주기억장치에서 저장해서 사용하는 개념이다.
=> 최근에는 거의 모든 데이터베이스에 이 기능을 내장
=> Apple에서 사용하는 In Memory DB 의 개념이 CoreData
** Core Data
=> Apple 의 In Memory DB의 개념
=> SQL을 이용하지 않고 데이터베이스를 사용 - ORM(Object Relation Mapping)
ORM의 개념을가진 프레임워크가 Java의 Hibernate, Node의 시퀄라이즈, Python의 Django, MS의 LINQ, Facebook의 GraphQL(Web Front End에서 최근에 많이 사용 등
ORM의 개념 대신에 이전의 SQL Mapper를 이용하기도 함 - SQL은 개발자들이 이미 알고 있는데 ORM은 새로 공부를 해야하고 SQL Mapper 방식은 데이터베이스 구조를 몰라도 사용할 수 있지만 ORM은 데이터베이스 구조를 정확하게 알고 있어야 한다.
1. Core Data 사용의 기본 개념
=> 프로젝트를 생성할때 Use Core Data를 선택하면 Core Data 사용에 필요한 객체를 미리 생성해 준다.
프로젝트를 생성할 때 설정하지 않은 경우에는 나중에 객체만 추가해주면 된다.
1) Persistency(영속) Container
=> Core Data를 사용할 수 있도록 해주는 객체
=> Documents 디렉토리에 프로젝트이름.sqlite 라는 파일로 존재
2) Data Model
=> 데이터 모델링을 수행해주는 개념
=> 프로젝트 이름.xcdatamodelID라는 파일로 존재
=> 더블클릭하면 Editor가 실행
=> Entity(개체) - 테이블(릴레이션)에 해당하는 개념
=> Attribute(속성) - 컬럼(필드)에 해당하는 개념
=> Relation(관계) - 2개 Entity 사이의 관계, 외래키나 조인에 해당하는 개념
3) Managed Object Context
=> DAO의 개념으로 NSManagedObjectContext 클래스의 인스턴스
=> Core Data를 사용하도록 만들면 AppDelegate의 persistencyContainer.viewContext를 이용해서 사용이 가능
=> save나 delete와 같은 메소드가 구현되어 있다.
=> Managed Object라는 클래스를 사용하는데 이 클래스가 DTO 클래스의 역할
** title(문자열), contents(문자열), runtime(날짜)의 컬럼을 갖는 ToDo라는 테이블을 생성하고 CRUD 작업을 수행 : CoreData 이용
=> 실제 포트폴리오나 프로젝트를 진행할 때는 안드로이도도 고려한다면 SQLite를 선택하는게 나을 수 있고 iOS만 하는 경우에는 Core Data를 사용하는 것이 나을 수 있다.
1. Core Data를 사용하는 프로젝트를 생성 ToDo
2. 필요한 테이블을 생성
1) ToDo.xcdatamodeld를 더블클릭해서 Editor를 실행
2) [Editor] - [Add Entity] 메뉴를 실행해서 Entity(ToDo)를 추가하고 이름을 수정
3) Entity를 선택하고 오른쪽 창에서 Attribute(title - 문자열, contents - 문자열, runtime - 날짜)를 추가하고 이름과 자료형을 설정
![]() |
3. 메인 화면에 TableViewController를 배치하고 상단에 네비게이션 바를 출력하도록 설정
1) UITableViewController롤 부터 상속받는 클래스 생성 - ToDoListVC
2) Main.storyboard에서 제공하는 ViewContoller를 제거
3) Main.storyboard에 TableViewController를 추가하고 Class 속성과 Storyboard ID 속성을 변경하고 is Initial View Controller 체크
4) [Editor] - [Embed In] - [Navigation Controller]를 실행해서 네비게이션 바 추가
4. 전체 데이터를 가져와서 출력부분 만들기
1) CoreData 임포트
import CoreData
2) 전체 데이터를 읽어오는 메소드를 생성
class ToDoListVC: UITableViewController {
//전체 데이터를 읽어오는 메소드
func fetch() -> [NSManagedObject]{
//1.AppDelegate 참조를 생성
let appDelegate = UIApplication.shared.delegate as! AppDelegate
//2.관리 객체 참조 만들기
let context = appDelegate.persistentContainer.viewContext
//3.ToDo 테이블에 작업을수행하기 위한 객체를 생성
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "ToDo")
//4.전체 데이터 가져오기
let result = try! context.fetch(fetchRequest)
return result
}
3) 전체 데이터를 저장하기 위한 변수를 생성
class ToDoListVC: UITableViewController {
//전체 데이터를 저장하기 위한 변수
//list를 처음 사용할 때 1번 fetch를 호출해서 결과를 저장
lazy var list : [NSManagedObject] = {
return self.fetch()
}()
4) 테이블 뷰 출력 관련 메소드 재정의
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return list.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//출력할 데이터 찾아오기
let record = list[indexPath.row]
//셀 만들기
var cell = tableView.dequeueReusableCell(withIdentifier: "cell")
if cell == nil{
cell = UITableViewCell(style: .subtitle, reuseIdentifier: "cell")
}
cell!.textLabel!.text = record.value(forKey: "title") as? String
cell!.detailTextLabel!.text = record.value(forKey: "contents") as? String
return cell!
}
5. 데이터 추가 작업
=> 새로운 뷰 컨트롤러에 데이터를 입력해서 입력한 내용을 Core Data에 저장하고 다시 출력
1) ToDoListViewController.swift 파일에 데이터를 저장하는 메소드를 생성
//데이터를 삽입하는 메소드
func save(title:String, contents:String, runtime:Date) -> Bool{
//1. 데이터베이스 객체 가져오기
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
//2. 추가할 데이터 생성
let object = NSEntityDescription.insertNewObject(forEntityName: "ToDo", into: context)
object.setValue(title, forKey: "title")
object.setValue(contents, forKey: "contents")
object.setValue(runtime, forKey: "runtime")
do{
//commit
try context.save()
//전체 데이터 다시 가져오기
//여러 유저가 공유하는 데이터라면 다시 가져오는 것이 돟다.
//self.list = self.fetch()
//데이터를 list에 추가
//ToDo 나 email처럼 혼자서만 사용하는 데이터라면 list에 바로 추가해도 된다.
//self.list.append(object)
//맨 앞에 추가
self.list.insert(object, at: 0)
return true
}catch{
//rollback
context.rollback()
return false
}
}
2) 입력화면으로 사용할 ViewController의 소스코드를 작성할 파일을 생성
=> UIViewController로부터 상속받는 ToDoInputVC
3) Main.storyboard 파일에 ViewController를 추가하고 Class 속성과 StoryboardID 속성을 변경 - ToDoInputVC
4) ToDoInputVC에 문자열 2개와 날짜를 입력받는 컨트롤을 배치하고 하단에 버튼을 2개 배치
=> 제목은 TextField, 내용은 TextView, 날짜는 DatePicker
=> 버튼은 취소와 확인
5)ToDoInputVC 에 디자인한 내용을 변수와 메소드로 연결
변수: tfTitle, tvContents, dpRuntime
메소드: cancel, save
6)ToDoInputVC.swift 파일에 cancel 메소드 작성
@IBAction func cancel(_ sender: Any) {
//현재 화면 제거
self.presentingViewController?.dismiss(animated: true)
}
7)ToDoInputVC.swift 파일에 add 메소드 작성
@IBAction func save(_ sender: Any) {
//자신을 호출한 ToDoViewController에 대한 참조를 생성
let naviVC = self.presentingViewController as! UINavigationController
let toDoListVC = naviVC.topViewController as! ToDoListVC
//삽입할 내용 가져오기
let title = tfTitle.text
let contents = tvContents.text
let runtime = dpRuntime.date
//데이터 삽입하고 결과 가져오기
let result = toDoListVC.save(title: title!, contents: contents!, runtime: runtime)
toDoListVC.dismiss(animated: true){() -> Void in
//삽입에 성공했으면 데이터 다시 출력
if result == true{
toDoListVC.tableView.reloadData()
}else{
let alert = UIAlertController(title: "데이터 삽입", message: "실패", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "확인", style: .default))
self.present(alert, animated: true)
}
}
}
8)ToDoListVC.swift 파일에 바 버튼 아이템이 호출할 메소드를 생성
//오른쪽 바 버튼이 호출할 메소드
@objc func add(_ sender:Any){
//ToDoInputVC 를 화면에 출력
let toDoInputVc = self.storyboard?.instantiateViewController(withIdentifier: "ToDoInputVC") as! ToDoInputVC
self.present(toDoInputVc, animated: true)
}
9)ToDoListVC.swift 파일의 viewDidLoad 메소드에 바 버튼을 추가하고 위에서 만든 메소드를 연결
override func viewDidLoad() {
super.viewDidLoad()
self.title = "To Do"
let addBtn = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(add(_:)))
self.navigationItem.rightBarButtonItem = addBtn
6. 삭제 구현
1) 데이터 삭제를 위한 메소드 작성
//데이터 삭제를 위한 메소드
func delete(object:NSManagedObject) -> Bool{
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
//데이터 삭제
context.delete(object)
do{
try context.save()
return true
}catch{
context.rollback()
return false
}
}
2) ToDoListVC.swift 파일의 viewDidLoad 메소드에 작성
//네비게이션 바의 왼쪽에 편집 버튼 추가
self.navigationItem.leftBarButtonItem = self.editButtonItem
3) edit 버튼을 눌렀을 때 보여질 버튼 모양을 설정하는 메소드를 작성
//편집 버튼을 누를 때 보여질 아이콘 모양을 설정하는 메소드
override func tableView(_ tableView:UITableView, editingStyleForRowAt indexPath:IndexPath) -> UITableViewCell.EditingStyle{
return .delete
}
4) 삭제 버튼을 눌렀을 때 수행할 작업을 설정하는 메소드를 작성
//삭제 버튼을 눌렀을 때 호출되는 메소드
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
//삭제할 데이터 찾기
let object = self.list[indexPath.row]
//삭제를 하고 성공하면
if self.delete(object: object){
self.list.remove(at: indexPath.row)
//self.tableView.reloadData()
self.tableView.deleteRows(at: [indexPath], with: .right)
}
}