[SwiftUI] CoreData의 DataModel을 이니셜 라이저 인수로받는 View의 Canvas Preview를 잘 작성
개요
예를 들어, 다음과 같은 Core Data의 Data Model을 상정합니다.
extension ToDo {
@nonobjc public class func fetchRequest() -> NSFetchRequest<ToDo> {
return NSFetchRequest<ToDo>(entityName: "ToDo")
}
@NSManaged public var id: UUID?
@NSManaged public var title: String?
@NSManaged public var content: String?
}
이 Data Model을 이니셜 라이저의 인수에 취하는 View를 적당하게 다음과 같이 씁니다.
import SwiftUI
struct ContentView: View {
var todo: ToDo
var body: some View {
VStack(alignment: .leading) {
Text(todo.title!)
Text(todo.content!)
}
}
}
이때, 이
ContentView
의 Canvas Preview를 표시하는 코드를 어떻게 쓰면 잘 되는지 고민했습니다.여러가지 구그한 결과, 이하의 기사를 발견했습니다.
해결
전제로 CoreData의
PersistenceController
주위의 코드를 하나의 구조체에 정리해 둡니다.import CoreData
struct PersistenceController {
static let shared = PersistenceController()
let container: NSPersistentCloudKitContainer
init() {
container = NSPersistentCloudKitContainer(name: "ToDo")
container.loadPersistentStores(completionHandler: { _, error in
if let error = error as NSError? {
print(error.localizedDescription)
}
})
}
static func saveContext() {
let context = Self.shared.container.viewContext
if context.hasChanges {
do {
try context.save()
} catch {
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
}
}
그리고 아래와 같은 Canvas Preview의 Wrapper가 되는 코드를 씁니다.
import CoreData
import SwiftUI
struct PreviewWrapper<Content: View>: View {
let content: (NSManagedObjectContext, ToDo) -> Content
var body: some View {
let context = PersistenceController.shared.container.viewContext
let todo = ToDo(context: context)
todo.id = UUID()
todo.title = "宿題"
todo.content = "算数のドリル10ページ、英単語の書取りの練習100語"
return self.content(context, todo)
}
init(@ViewBuilder content: @escaping (NSManagedObjectContext, ToDo) -> Content) {
self.content = content
}
}
이렇게하면 중요한 Canvas Preview 코드를 다음과 같이 작성할 수 있습니다.
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
PreviewWrapper { _, todo in
ContentView(todo: todo)
}
}
}
Canvas Preview는 다음과 같습니다.
List의 경우는?
예를 들어, 다음과 같이 이니셜 라이저에 [ToDo] 형의 인수를 취하는 List를 표시하고 싶을 때는 어떻습니까?
코드의
ContentView
는 이전 예제의 ContentView
를 그대로 사용합니다.import SwiftUI
struct ContentListView: View {
var todos: [ToDo]
var body: some View {
List {
ForEach(todos) { todo in
ContentView(todo: todo)
}
}
}
}
이 경우는 예로서 다음과 같이 Preview의 Wrapper를 만들어 해결할 수 있습니다.
[ToDo]형의 배열의 길이는 적당히 10으로 하고 있습니다.
struct PreviewListWrapper<Content: View>: View {
let content: (NSManagedObjectContext, [ToDo]) -> Content
var body: some View {
let context = PersistenceController.shared.container.viewContext
let todo = ToDo(context: context)
let todos: [ToDo] = ([Int])(0 ..< 10).map { _ in
todo.id = UUID()
todo.title = "宿題"
todo.content = "算数のドリル10ページ、英単語の書取りの練習100語"
return todo
}
return self.content(context, todos)
}
init(@ViewBuilder content: @escaping (NSManagedObjectContext, [ToDo]) -> Content) {
self.content = content
}
}
Canvas Preview 코드:
struct ContentListView_Previews: PreviewProvider {
static var previews: some View {
PreviewListWrapper { _, todos in
ContentListView(todos: todos)
}
}
}
Canvas Preview:
Reference
이 문제에 관하여([SwiftUI] CoreData의 DataModel을 이니셜 라이저 인수로받는 View의 Canvas Preview를 잘 작성), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/koralle/items/71204ee06560a2f8db09텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)