-
Core Data with SwiftUI Tutorial: Getting StartedRaywenderlich/Articles 2020. 12. 9. 15:28
www.raywenderlich.com/9335365-core-data-with-swiftui-tutorial-getting-started
Core Data with SwiftUI Tutorial: Getting Started
In this Core Data with SwiftUI tutorial, you’ll learn to persist data in an app using @State, @Environment and @FetchRequest property wrappers.
www.raywenderlich.com
Version
Swift 5, iOS 13, Xcode 11
다음 번에 앱(app)을 열 때, Notes에 적어둔(jotting down) 중요(important) 내용이 사라진다는 것을 상상하면 끔찍하다. 다행히도(fortunately) iOS의 지속성(persistence)은 훌륭하다. Core Data 덕분에 모든 메모(notes), 사진(photos), 기타 데이터(data)는 안전하다.
앱(app) 실행(launches) 전반에 데이터를 저장(store)해야 할 때 사용할 수 있는 다양한 기술(technologies)이 있다. Core Data는 iOS에서 사용할 수 있는 해결책(solution)이다. 인상적인(impressive) 성능(performance)과 다양한(broad) 기능(features)을 갖춘 Apple의 Core Data 프레임 워크(framework)는 앱(app)의 전체(entire) 모델 계층(model layer)을 관리(manages)하고, 기기(device)의 저장 디스크(storage disk)에 대한 지속성(persistence)을 처리(handles)한다.
이 Core Data with SwiftUI 튜토리얼(tutorial)에서는 앱(app)을 리팩토링(refactor)하고 지속성(persistence)을 추가하여 앱(app)이 다시 시작(restarts)될 때 데이터가 손실되는 악몽(nightmare)을 방지(prevent)한다. 그 과정에서 다음을 배우게 된다:
- 프로젝트(project)에서 Core Data를 설정(set up)한다.
- SwiftUI의 데이터 흐름(data flow)을 사용하여, Core Data 프레임 워크(framework)에서 필요한 항목에 접근(access)한다.
- Core Data를 사용하여 새로운 모델(model) 객체(objects)를 정의(define)하고 생성한다.
- Fetch Requests을 사용하여, 디스크(disk)에서 객체(objects)를 가져(retrieve)온다.
이제 Core Data의 기능(capabilities)과 작동 방식(how it works)에 대해 자세히 알아본다.
Getting Started
시작하려면 이 튜토리얼(tutorial)의 상단(top) 또는 하단(bottom)에 있는 Download Materials 버튼(button)을 사용하여 프로젝트(project) 자료(materials)를 다운로드(download) 한다. Xcode에서 시작(starter) 프로젝트(project)를 연 후에, 빌드(build)하고 실행(run)한다.
FaveFlicks 앱은 개인(personal)적으로 선호하는(favorite) 영화를 기록(tally)한다. 목록(list)에 영화를 추가(add)하거나 삭제(delete)할 수 있는 간단한 앱이다. 그러나(however), 한 가지 분명한(glaring) 문제(problem)가 있다.
앱(app)은 데이터를 유지(persist)하지 않는다. 즉, 목록(list)에 일부 영화를 추가한 다음 앱을 재시작(restart)하면 신중하게(carefully) 추가(added)한 영화가 사라진다.
Testing FaveFlick’s Persistence
목록(list)에서 영화를 제거하려면, 왼쪽으로 밀어(swipe) Delete를 탭(tap)한다.
그런 다음 오른쪽 상단(top-right)의 Plus 버튼(button)을 탭(tap)하여, 즐겨찾기(favorites) 중 하나를 추가(add)한다.
영화 추가(Add Movie) 화면(screen)이 표시된다.
각
Movie
객체(object)는 메모리에만 존재(exists)한다. 디스크(disk)에 저장(stored)되지 않으므로, 앱(app)을 닫으면 변경 사항(changes)이 제거(removes)되고 영화 즐겨찾기(favorite) 목록(list)으로 돌아간다.Note: "add movie" 화면(screen)을 두 번째로 열려고 하면 아무 일도 일어나지 않는다(nothing happens). 이는 SwiftUI의 알려진 Apple 버그이다. 해결 방법(workaround)으로 어떤 방식으로든 영화를 추가하여, UI를 업데이트(update)해야 한다. 목록(list)을 아래로 당겨서(pull down) UI를 업데이트(update)한 다음, 더 많은 영화를 추가(add)할 수 있다.
앱(app)을 강제 종료(force close)하여 지속성(persistence)을 확인(test)한다. 앱(app)이 전면(foreground)에 있는 상태에서 빠른 앱 전환 화면(fast app switcher)으로 들어간다(enter). 이렇게 하려면 화면(screen)의 하단(bottom)에서 부드럽게(gently) 위로 드래그(drag up)한다. 홈 버튼이 있는 기기(device)에서 빠른 앱 전환(fast app switcher)을 사용하려면 홈(Home) 버튼(button)을 두 번 탭(double-tap)한다.
이제 FaveFlicks를 선택(select)하고 위로 스와이프(swipe up)하여 앱(app)을 닫는다(close). 그리고 홈 화면(home screen)에서 FaveFlicks를 탭(tap)하여 다시 연다.
변경 사항(changes)이 사라지고(gone), 기본(default) 영화가 다시 표시되는 것을 확인할 수 있다.
문제를 해결(fix)해야할 때이다. 먼저 Core Data를 설정한다.
Setting Up Core Data
지속성(persistence) 설정(setting up)을 시작하기 전에, Core Data stack 이라고도 하는 Core Data의 운송(moving) 부분에 대해 알아야 한다. Core Data stack에는 다음이 포함(includes)된다:
- managed object model은 엔티티(entities)라고 하는 모델(model) 객체(objects)와 다른 엔티티(entities)와의 관계(relationships)를 정의(defines)한다. 이를 데이터베이스(database) 스키마(schema)라고 생각하면 된다. FaveFlicks에서는 FaveFlicks.xcdatamodeld 내(inside)의 managed object model 일부로
Movie
엔티티(entity)를 정의(define)한다. NSManagedObjectModel 클래스(class)를 사용하여, 코드에서 managed object model에 접근(access)한다. - NSPersistentStoreCoordinator는 실제 데이터베이스(database)를 관리(manages)한다.
- NSManagedObjectContext는 엔터티(entities)를 생성(create), 편집(edit), 삭제(delete) 또는 가져올(retrieve) 수 있는 메모리 스크래치 패드(in-memory scratchpad)이다. 일반적으로(usually) Core Data와 상호 작용(interacting)할 때 managed object context로 작업한다.
Scratchpad memory : en.wikipedia.org/wiki/Scratchpad_memory
이제 시작해볼 시간이다(it’s time to get started).
Adding the Core Data stack
전체(entire) Core Data stack을 설정(set up)하는 것은 어려워 보일 수 있지만,
NSPersistentContainer
덕분에 쉽게 구성할 수 있다. 이를 사용해 모든 것을 만들 수 있다. SceneDelegate.swift를 열고import SwiftUI
다음에 아래 코드를 추가한다:import CoreData
Core Data는 자체(own) 프레임 워크(framework)이므로, 이를 사용하려면 반드시 가져와야(import) 한다.
이제
SceneDelegate
의 끝에 다음을 추가한다:lazy var persistentContainer: NSPersistentContainer = { //lazy 속성으로 persistentContainer를 추가한다. //해당 속성을 처음 참조할 때, NSPersistentContainer가 생성된다. let container = NSPersistentContainer(name: "FaveFlicks") //FaveFlicks 이름의 container를 생성한다. //이 프로젝트에는 이미 FaveFlicks.xcdatamodeld가 있으며, 이 파일은 Core Data의 model schema를 설계한다. //해당 파일의 이름은 container의 이름과 일치해야 한다. container.loadPersistentStores { _, error in //Core Data stack을 설정하는 persistent store를 로드한다. if let error = error as NSError? { // You should add your own error handling code here. fatalError("Unresolved error \(error), \(error.userInfo)") //error가 발생하면 이를 기록하고 앱을 종료시킨다. //실제 앱에서는 앱의 state가 비정상이며 재설치가 필요하다는 dialog를 표시하여 처리한다. //이 error는 발생할 확률이 매우 낮고 개발자의 실수로 인한 것이므로, App Store에 출시하기 전에 처리할 수 있어야 한다. } } return container }()
이것이 Core Data stack을 설정(set up)하는 데 필요한 전부이다. 정말 좋다(Quite a journey).
Core Data는 자동으로(automatically) 처리(handle)되지 않기 때문에, 데이터를 디스크(disk)에 저장(saving)하는 방법도 필요하다. SceneDelegate.swift에서 클래스(class)의 끝에 다음 메서드(method)를 추가한다:
func saveContext() { let context = persistentContainer.viewContext //persistent container의 viewContext를 얻는다. //이는 main thread에서만 사용되도록 지정된 특별한 managed object context이다. //저장되지 않은 data를 저장하는데 이를 사용한다. if context.hasChanges { //저장할 변경 사항이 있는 경우에만 저장한다. do { try context.save() //context를 저장한다. 이 호출은 error를 발생시킬 수 있으므로 try/catch로 감싼다. } catch { // The context couldn't be saved. // You should add your own error handling here. let nserror = error as NSError fatalError("Unresolved error \(nserror), \(nserror.userInfo)") //error가 발생하면, 이를 기록하고 앱이 종료된다. //이전 method에서와 마찬가지로 여기의 모든 error는 개발 중에서만 발생해야 한다. //하지만 만약의 경우를 대비해 app에서 적절하게 처리한다. } } }
이제 Core Data stack을 설정(set up)하고, 변경 사항(changes)을 저장(save)하는 메서드(method)가 있으므로, 이를 앱(app)의 나머지 부분에 연결(wire)할 차례이다.
이제
scene(_:willConnectTo:options:)
에서let contentView = MovieList()
를 다음으로 바꾼다(replace):let context = persistentContainer.viewContext let contentView = MovieList().environment(\.managedObjectContext, context)
이전에 사용한 것과 동일한
viewContext
를 가져와(grabs),MovieList
SwiftUI 뷰(view)의 환경 변수(environment variable)로 설정(sets)한다. 뷰(view)는 나중에 이를 사용하여 Core Data 저장소(store)에 영화를 추가(add)하고 제거(remove)한다.이제
SceneDelegate
끝에 다음 메서드(method)를 추가한다:func sceneDidEnterBackground(_ scene: UIScene) { saveContext() }
이렇게 하면 앱(app)이 백그라운드(background)로 전환될 때, 이전에 추가한 save 메서드(method)를 호출(call)한다. 해당 상황은 데이터를 디스크(disk)에 저장(save)하기 좋은 상황이다. 더 자주(frequently) 저장하는 방법에 대해서는 이후에 알아볼 것이다.
빌드(build)하고 실행(run)하여, 앱(app)이 제대로 작동하는지 확인한다. 아직 기능적(functional)인 변경 사항(changes)은 없다.
Creating the Data Model
이제 Core Data stack을 벗어나, 드디어 앱(app)의 주요 부분(main part)을 작업할 차례이다. Xcode에서 FaveFlicks.xcdatamodel을 연다. 지금은 비어(empty) 있지만, 아래에서
Movie
엔티티(entity)를 선언(declare)할 것이다. 여기에서 데이터 모델(data model)의 스키마(schema)를 정의(define)한다. 생성할 수 있는 객체(objects) 유형(types)인 관련(relevant) 엔티티(entities)를 추가하고, 엔티티(entities)가 연결(connected)되는 방식을 나타내는(indicate) 관계(relationships)를 정의(define)한다.엔티티 추가(Add Entity)를 클릭(click)한다.
Xcode는 데이터 모델(data model)에서, 기본적(default)으로 Entity라는 새 엔티티(entity)를 생성한다. 이름을 두 번 클릭(Double-click)하여 Movie로 변경(change)한다.
다음으로 Attributes 아래의 + 아이콘(icon)을 클릭(click)하여 새 속성(attribute)을 추가한다. 이름을 title로 지정하고, 유형(type)을 String로 설정한다.
마지막으로(finally), 두 개의 속성(attributes)을 추가한다. 하나는 String 유형(type)의 genre이고, 다른 하나는 Date 유형(type)의 releaseDate이다. 완료(done)되면,
Movie
엔티티(entity)의 속성(attributes)은 다음과 같다:Relationships and Fetched Properties
FaveFlicks에는
Movie
라는 하나의 엔터티(entity)만 있지만, 더 큰 데이터 모델(data models)을 사용하는 앱(apps)에서는 관계(relationships)를 설정(run into)하고 속성(properties)을 가져올(fetched) 수 있다. 관계(relationship)는 모든 데이터베이스(database)의 관계(relationship)와 동일하게, 두 엔티티(entities) 간의 관계(relationships)를 정의(define)할 수 있다.그러나 Fetched properties는 고급(advanced) Core Data 주제(topic)이다. weak 단방향(one-way) 관계(relationships)처럼 작동하는 computed properties로 생각할 수 있다. 예를 들어(for instance) FaveFlicks에
Cinema
엔터티(entity)가 있는 경우, 현재 영화관에서 상영 중인 영화를 가져 오는 currentShowingMovies라는 fetched property가 있을 수 있다.Note: 이 두 가지 모두에 대한 자세한 정보(information)와 더 많은 자료를 원한다면 Core Data by Tutorials를 확인(check out)해 본다.
Removing the Old Movie Struct
Movie.swift를 연다. 이 튜토리얼(tutorial)을 시작할 때, Movie 구조체(struct)는 모델(model) 객체(object)였다. Core Data는 자체
Movie
클래스(class)를 생성하므로 Movie.swift를 제거(remove)해야 한다. 프로젝트 탐색기에서 Movie.swift를 마우스 오른쪽 버튼으로 클릭(right-clicking)하고, Delete를 선택하여 삭제(delete)한다. 표시되는 대화 상자(dialog)에서 Move to Trash을 클릭(click)한다.앱(app)을 빌드(build)한다. 방금
Movie
를 삭제(removed)했기 때문에, 수정(fixing)해야 하는 몇 가지 오류(a couple of errors)가 표시된다.Note: 이 섹션(section)에서 이전 Movie 구조체(struct)에 대한 코드를 정확(precise)하게 삭제(delete)해야 하므로 자세히 확인한다.
먼저 MovieList.swift를 연다. 간단하게
movies
배열(array)에 저장(stored)된 영화 목록(list)을 확인할 수 있다.MovieList
의 상단(top)에서movies
배열(array)을 선언(declaring)하는 행(line)을, 아래와 같이 빈(empty) 배열(array)로 변경(change)한다:@State var movies: [Movie] = []
@State
속성 래퍼(property wrapper)는 SwiftUI 데이터 흐름(data flow)의 중요한 부분(vital piece)이다. 이 로컬 속성(local property)을 선언(declares)하는 클래스(class)가 이를 소유(owns)한다.movies
의 값(value)이 변경(changes)되면, 이를 소유한(owns) 뷰(view)는 UI 업데이트(update)를 실행(trigger)한다.이제
makeMovieDefaults()
는 더 이상 사용되지 않으므로, 삭제(delete)한다.addMovie(title:genre:releaseDate:)
에서 영화가 생성되고,movies
배열(array)에 추가(added)된다. 해당 내용(contents)을 제거(remove)하고 빈(blank) 메서드(method)로 남겨둔다. 이후 섹션(section)에서 이를 사용하여,Movie
엔티티(entity)의 새 인스턴스(instances)를 만든다.마지막으로
deleteMovie(at:)
의 내용(contents)을 제거(remove)한다. 나중에 이를 Core Data의 엔티티(entities)를 삭제(deletes)하는 코드로 대체(replace)한다.Using the New Movie Entity
이제 데이터 모델(data model)에서
Movie
엔티티(entity)를 만들었으므로, Xcode는 대신(instead) 사용할 자체Movie
클래스(class)를 자동으로 생성(auto-generate)한다. 데이터 모델(data model)의 모든 엔티티(entities)는NSManagedObject
의 하위 클래스(subclasses)이다. Core Data는 주로 Managed Object Context를 사용하여 Core Data의 수명주기(lifecycle)와 지속성(persistence)을 처리(handles)하므로, 엔티티는 managed object이다.이전(old)
Movie
구조체(struct)는 옵셔널(optional) 속성(properties)을 사용하지 않았다. 그러나 모든NSManagedObject
하위 클래스(subclasses)는 해당 속성(attributes)에 대해 옵셔널(optional) 속성(properties)을 사용한다. 즉,Movie
를 사용하는 파일(files)을 일부 변경(changes)해야 한다.Note: 모든 속성(properties)이 옵셔널(optional)인 경우의 예외(exception) 사항은 스칼라(scalar) 유형(types)이다. 예를 들어(for example), 엔터티(entity)에
Float
속성(property)이 있고 Use Scalar Type이 활성화(enabled)된 경우, 생성(generated)된 속성(property)은 비 옵셔널(non-optional)Float
유형(type)이 된다.Using an Entity’s Attributes in a View
이제 뷰(view)에서 엔티티(entity)의 속성(attributes)을 사용하는 방법을 배운다. MovieRow.swift를 열고, body 속성(property)을 다음으로 바꾼다(replace):
var body: some View { VStack(alignment: .leading) { // 1 movie.title.map(Text.init) .font(.title) HStack { // 2 movie.genre.map(Text.init) .font(.caption) Spacer() // 3 movie.releaseDate.map { Text(Self.releaseFormatter.string(from: $0)) } .font(.caption) } } }
뷰(view)의 구조(structure)는 정확히 동일하지만, 모든
movie
의 속성(attributes)이View
에 매핑(mapped)되어 있음을 알 수 있다.Core Data 엔터티(entity)의 모든 속성(attributes)은 옵셔널(optional)이다. 즉,
title
속성(optional)은String?
유형(type)이고referenceDate
는Date?
유형(type)이다. 따라서 이제 옵셔널(optional)의 값(value)을 얻을 방법이 필요하다.MovieRow
의body
속성(property)과 같은ViewBuilder
에서는, 내부(inside)에if let
과 같은 제어 흐름(control flow) 구문(statements)을 추가할 수 없다. 각 행(line)은View
또는nil
이어야 한다.위의
1
,2
,3
으로 표시된 행(line)은 속성(attributes)이 nil이 아닌 경우(non-nil),Text
뷰(view)가 된다. 그렇지 않으면(otherwise)nil
이 된다. 이는 SwiftUI 코드에서 옵셔널(optionals)을 처리(deal with)하는 편리한(handy) 방법이다.마지막으로 빌드(build)하고 실행(run)한다. 이전(old)
Movie
구조체(struct)를 제거(removed)하고 Core Data 엔터티(entity)로 대체(replaced it with)했다. 그에 대한 보상(reward)으로, 이제는 세련된(classy) 영화 목록(list)이 아닌 빈(empty) 뷰(view)를 갖게 된다.영화를 생성해도, 아무 일이 일어나지 않는다(nothing happens). 다음으로 이 문제를 해결한다.
Using Environment to Access Managed Object Context
다음으로 managed object context에서 객체(objects)에 접근(access)하는 방법을 배운다. MovieList.swift로 돌아가,
movies
선언(declaration) 아래에 다음 행(line)을 추가한다:@Environment(\.managedObjectContext) var managedObjectContext
이전에
MovieList
에서managedObjectContext
환경 변수(environment variable)를 설정했다. 이제 그것에 접근(access)할 수 있게 선언(declaring)한다.@Environment
는 전역(global) 속성(properties)에 접근(access)할 수있는 SwiftUI 데이터 흐름(data flow)의 또 다른 중요한 부분(important piece)이다. 환경 객체(environment object)를 뷰(view)에 전달(pass)하려면, 객체(object)를 생성할 때 전달(pass)한다.이제 MovieList.swift에 다음 메서드(method)를 추가한다:
func saveContext() { do { try managedObjectContext.save() } catch { print("Error saving managed object context: \(error)") } }
엔터티(entities)를 생성(create), 업데이트(update) 또는 삭제(delete)할 때, 메모리 스크래치 패드(in-memory scratchpad)인 managed object context에서 이를 수행한다. 실제로 변경 사항(changes)을 디스크(disk)에 기록(write)하려면, 컨텍스트(context)를 저장(save)해야 한다. 이 메서드(method)는 새로운 객체(objects) 또는 업데이트(updated)된 객체(objects)를 영구 저장소(persistent store)에 저장(saves)한다.
다음으로,
addMovie(title:genre:releaseDate:)
를 찾는다. 이전Movie
를 제거하고 메서드(method)는 여전히 비어 있으므로, 아래 메서드(method)로 대체(replace)하여 새Movie
엔터티(entities)를 생성한다:func addMovie(title: String, genre: String, releaseDate: Date) { let newMovie = Movie(context: managedObjectContext) //managed object context에서 새로운 Movie를 생성한다. newMovie.title = title newMovie.genre = genre newMovie.releaseDate = releaseDate //addMovie(title:genre:releaseDate:)로 전달된 매개변수를 Movie의 모든 속성에 설정한다. saveContext() //managed object context를 저장한다. }
빌드(build)하고 실행(run)한 후, 새 영화를 생성한다. 여전히 빈(blank) 목록(list)이 표시된다.
영화를 만들었지만, 목록(list)에 표시(display)하기 위해 가져오지(retrieving) 않았기 때문이다. 다음 섹션(section)에서 이 문제를 해결(fix)하면, 마침내 앱(app)에서 영화를 다시 보게 될 것이다.
Fetching Objects
이제 생성한 영화를 표시(display)하는 방법을 배운다. FetchRequest를 사용하여 영구 저장소(persistent store)에서 이를 가져와야(fetch) 한다.
MovieList
의 상단(top)에서movies
배열(array)을 선언(declaring)하는 행(line)을 제거(remove)한다. 그리고 이를 FetchRequest로 바꾼다(replace):@FetchRequest( //@FetchRequest 속성 래퍼를 사용하여 속성을 선언하면, SwiftUI 뷰에서 결과를 직접 사용할 수 있다. entity: Movie.entity(), //속성 래퍼 내에서 가져올 Core Data 엔티티를 지정한다. //여기서는 Movie 엔티티의 instances를 fetch한다. sortDescriptors: [ //결과의 순서를 결정하기 위해, sort descriptors 배열을 추가한다. //예를 들어, genre별로 영화를 정렬한 다음 같은 genre의 영화에 대해서는 title별로 정렬할 수 있다. NSSortDescriptor(keyPath: \Movie.title, ascending: true) //여기서는 단순하게 title로 정렬한다. ] ) var movies: FetchedResults<Movie> //마지막으로, property wrapper 다음에 FetchedResults 유형의 movies 속성을 선언한다.
Core Data에서 엔티티(entities)를 가져와야(retrieve) 하는 경우,
FetchRequest
를 생성한다.Predicates
위의 구현은 Core Data에 저장(stored)된 모든
Movie
를 가져온다(fetch). 그러나 객체(objects)를 필터링(filter)해야 하거나 특정(specific) 엔티티(entity) 하나만 가져와야(retrieve) 하는 경우가 있을 수 있다. 또한 특정(certain) 연도(year) 또는 특정 (certain) 장르(genre)의Movie
만 가져오는(fetching) 것과 같이, 결과를 제한(limit)하는 predicate를 사용하여 fetched request를 구성(configure)할 수도 있다. 그렇게 하려면 다음과 같이@FetchRequest
속성 래퍼(property wrapper) 끝에predicate
매개 변수(parameter)를 추가한다:predicate: NSPredicate(format: "genre contains 'Action'")
지금은 fetch request이 모든
Movie
를 가져와야 하므로, 추가할 필요가 없다. 하지만 결과를 확인해 보고 싶다면 꼭 해보는 것이 좋다(if you want to play around with this then by all means do).Testing the Results
빌드(build)하고 실행(run)한다. 영화의 목록(list)이 표시된다.
처음 시작한 곳으로 돌아왔다. 영화가 디스크(disk)에 저장(storing)되는지 확인(test)하려면 몇 개를 추가한 다음, Xcode에서 중지(stop)를 눌러 앱을 종료(kill the app )한다. 그런 다음 다시 빌드(build)하고 실행(run)한다. 모든 영화는 그대로 유지된다.
Deleting Objects
다음으로 객체(objects)를 삭제(delete)하는 방법을 배운다. 왼쪽으로 스와이프(swipe left)하고 영화를 삭제(delete)하려고 하면 아무 일도 일어나지 않는다(nothing happens). 이 문제를 해결(fix)하려면
deleteMovie(at:)
를 다음으로 바꾼다(replace):func deleteMovie(at offsets: IndexSet) { offsets.forEach { index in //SwiftUI의 List는 목록에서 객체를 삭제하기 위해 swipe할 때, 삭제할 IndexSet를 제공한다. //forEach를 사용하여 IndexSet을 반복한다. let movie = self.movies[index] //현재 index에 대한 movie를 가져온다. self.managedObjectContext.delete(movie) //managed object context에서 movie를 삭제한다. } saveContext() //context를 저장하여, 변경사항을 디스크에 유지한다. }
빌드(build)하고 실행(run)한 다음, 영화를 삭제(delete)한다.
앱의 모든 기능(functionality)을 복원(restored)했으며, 게다가 Core Data 덕분에(thanks to) 아침에도 앱(app)이 그대로 있을 것이다.
Where to Go From Here?
Core Data를 사용하여 SwiftUI 프로젝트(project)에 지속성(persistence)을 도입(introduce)하고, 엔티티(entities)를 디스크(disk)에 저장(store)했다. 이 튜토리얼(tutorial)의 상단(top) 또는 하단(bottom)에 있는 Download Materials 버튼(button)을 사용하여, 완성(completed)된 프로젝트(project)를 다운로드(download)할 수 있다.
Core Data 및 SwiftUI에 대한 더 많은 실제(hands-on) 경험(experience)을 원한다면, 다음 튜토리얼(tutorials)들을 확인해 본다:
Core Data는 방대한(huge) 주제(topic)이며, 아직 배워야 할 것이 많다. UIKit을 사용한 Core Data에 대해 자세히 알아 보려면, Core Data by Tutorials를 살펴본다.
이 튜토리얼(tutorial)에서 데이터 흐름(data flow)에 대해 꽤(a fair bit of) 살펴 보았지만, 자세히 알아보려면 WWDC 2019의 Data Flow Through SwiftUI 비디오를 살펴볼 수 있다.
데이터 흐름(data flow)뿐만 아니라 SwiftUI 마스터(master)가 되기 위한 모든 것이 필요하다면, SwiftUI by Tutorials에서 필요한 부분을 확인해 본다.
SwiftUI 덕분에(thanks to) Core Data 설정(set up)이 그 어느 때보다 쉬워졌다(easier than ever before). 이 Core Data with SwiftUI Tutorial 튜토리얼(tutorial)이 즐거웠기를 바란다. 공유할(share) 질문(questions)이나 통찰(insights)이 있다면, 아래의 포럼(forum)에 참여(join)할 수 있다.
'Raywenderlich > Articles' 카테고리의 다른 글
Getting Started With Widgets (0) 2021.02.03 How To Secure iOS User Data: Keychain Services and Biometrics with SwiftUI (0) 2020.12.13 Fastlane Tutorial: Actions and Plugins (0) 2020.12.02 Alamofire Tutorial for iOS: Advanced Usage (0) 2020.11.23 Alamofire 5 Tutorial for iOS: Getting Started (0) 2020.11.23