SwiftUI PreviewProvider использует CoreData для отображения конкретной записи NSManagedObject

0

Вопрос

[Xcode 12.4, Каталина 10.15.6, проект macOS с использованием SwiftUI и CoreData]

Я работаю над приложением для отображения некоторых имеющихся у меня данных. Бизнес-логика приложения работает нормально, и теперь я обратил свое внимание на пользовательский интерфейс. Для того, чтобы привести в порядок пользовательский интерфейс, я хотел бы получить PreviewProvider работает для каждого вида. Я также хотел бы, чтобы предварительные просмотры отображали данные, которые у меня уже есть в хранилище данных CoreData.

После многих разочарований мне наконец удалось скомпилировать и отобразить предварительный просмотр, однако я не вижу никаких фактических данных в предварительном просмотре. Похоже, что, хотя NSManagedObjectContext присутствует, предварительный просмотр не выбрал ни одной записи для отображения.

Как я могу выбрать, скажем, 3-ю запись в моем хранилище данных, которая будет отображаться в предварительном просмотре?

Ниже приведен мой код для представления, которое включает в себя PreviewProvider в конце (как обычно) с некоторыми комментариями, объясняющими это ниже.

    
    
    import SwiftUI
    
    struct DomainRow: View {
      
      @Environment(\.managedObjectContext) var context
      @ObservedObject var domain : DomainFiles
      private var id : LocalizedStringKey {
        get {
          return LocalizedStringKey(String(Int(domain.id)))
        }
      }
      
      var body: some View {
        HStack (alignment: .center) {
          Text(id)
          Spacer()
          VStack(alignment: .leading) {
            Text(domain.name!)
              .fontWeight(.bold)
              .truncationMode(.tail)
              .frame(minWidth: 20)
    
            Text(domain.path!)
              .font(.caption)
              .opacity(0.625)
              .truncationMode(.middle)
          }
        }
        .padding(.vertical, 4)
      }
    }
    
    #if DEBUG
    struct DomainRow_Previews: PreviewProvider {
    
      @Environment(\.managedObjectContext) var managedObjectContext
    
      static var previews: some View {
        let context = CoreDataStack.context
        let domain = DomainFiles(context: context)
        return DomainRow(domain: domain)
          .environment(\.managedObjectContext, CoreDataStack.context)
      }
    }
    #endif

DomainFiles является сущностью CoreData (с парой тысяч записей), каждая из которых имеет несколько атрибутов, которые включают id, name, и path (в файл). CoreDataStack.context это ссылка на структуру, показанную ниже.

Чтобы получить статический NSManagedObjectContext, как того требует поставщик предварительного просмотра, я добавил в свой проект следующую структуру в соответствии с https://developer.apple.com/forums/thread/650269

    import Foundation
    import CoreData
    
    struct CoreDataStack {
        static var context: NSManagedObjectContext {
            return persistentContainer.viewContext
        }
      
        static let containerName: String = "MyAppsDataStore"
    
        static var persistentContainer: NSPersistentContainer = {
            let container = NSPersistentContainer(name: containerName)
            container.loadPersistentStores { (description, error) in
                if let error = error {
                    print(error)
                }
            }
            return container
        }()
    //    Don't need to save anything in the preview.
    //    func saveContext() { ... }
    }

Я бы, например, хотел передать запись с domain.id == 3 в предварительный просмотр. Как я могу это сделать? (Заранее спасибо за ваше внимание.)

core-data swiftui
2021-11-17 02:43:02
1

Лучший ответ

0

Я выяснил, чего не хватало в моем PreviewProvider структура:

  1. Мне нужно было выполнить запрос Nsfetch, чтобы получить данные.
  2. Затем я смог получить доступ к записям в хранилище данных, используя индекс массива.
    Обратите внимание, что индекс является внутренним представлением CoreData, и если вам нужен конкретный элемент, используйте SQLite чтобы просмотреть хранилище данных и найти то, которое вы хотите увидеть.
struct EntriesView_Previews: PreviewProvider {

  @Environment(\.managedObjectContext) var managedObjectContext

  static var previews: some View {
    let context = CoreDataStack.context
    let domainFiles : [DomainFiles]
    let requestDomainFiles : NSFetchRequest<DomainFiles> = DomainFiles.fetchRequest()
    do {
      domainFiles = try context.fetch(requestDomainFiles)
    } catch {
      let nserror = error as NSError
      fatalError("Error \(nserror): \(nserror.userInfo)")   //  DO NOT DO THIS IN REAL CODE.  PROVIDE FALLBACK
    }
    let domain = domainFiles[0]
    return EntriesView(domain: domain)
      .environment(\.managedObjectContext, CoreDataStack.context)
  }
}
2021-11-17 05:01:43

На других языках

Эта страница на других языках

Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................