Post

Replies

Boosts

Views

Activity

Unit Testing with Swift Data
Hi, I'm wondering if anyone has a suggestion as to how to access a ModelContainer in the Unit Testing class. I tried making a class to only instantiate the model container once, but it seems that Xcode is running this class in two different contexts (and they don't communicate): once when the test launches and then again from inside the XCTestCase subclass. If I try to save, I get an error about the two containers not being the same or a ton of validation errors. Appreciate any help to point me in the right direction. import SwiftUI import SwiftData @main struct MyApp: App { var body: some Scene { WindowGroup { ContentView() } .modelContainer(MyModelContainer.shared.container) } } @MainActor final class MyModelContainer { private init() { } @MainActor static var shared = MyModelContainer() var container: ModelContainer { if let internalContainer { return internalContainer } let schema = Schema([ MyModel.self ]) if ProcessInfo.processInfo.environment["XCTestConfigurationFilePath"] != nil { // testing internalContainer = previewContext(with: schema) } else if ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1" { // previewing internalContainer = previewContext(with: schema) } else { // production internalContainer = productionContext(with: schema) } return internalContainer! } private var internalContainer: ModelContainer? private func previewContext(with schema: Schema) -> ModelContainer { let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: true) do { let previewData = fetchPreviewData() let container = try ModelContainer(for: schema, configurations: [modelConfiguration]) let context = container.mainContext context.insert(previewData) try context.save() print("Loaded preview Container \(Date.now)") return container } catch { print("Could not create ModelContainer: \(error)") fatalError("Could not create ModelContainer: \(error)") } } func productionContext(with schema: Schema) -> ModelContainer { let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false) do { print("Loaded FlashMeContainer") return try ModelContainer(for: schema, configurations: [modelConfiguration]) } catch { fatalError("Could not create ModelContainer: \(error)") } } } final class FlashMeTests: XCTestCase { @MainActor func testImport() throws { let data = NSDataAsset(name: "myCodableModelData")?.data let myCodableModel = try oldData!.decode(as: MyCodableModel.self) let myModel = myCodableModel.convertToSwiftData() let context = MyModelContainer.shared.container.mainContext context.insert(myModel) try context.save(myModel) } }
1
0
1.2k
Sep ’23
@SectionedFetchRequest Not Updating
I'm working to implement an infinite scrolling view using @SectionedFetchRequest. I'm able to update Core Data to reflect the new sections and order-within-the-section. @SectionedFetchRequest is correctly fetching and organizing everything on launch, but it's not updating as I update Core Data. I am using a SQLite app to simulate the Core Data query, and I can see @SectionedFetchRequest isn't picking up on everything that's there. Any thoughts as to what might be going on? extension CDArticle { static func displayFetchRequest() -> NSFetchRequest<CDArticle> {         let request: NSFetchRequest<CDArticle> = fetchRequest()         request.sortDescriptors = [NSSortDescriptor(keyPath: \CDArticle.sectionFolder, ascending: true),                                    NSSortDescriptor(keyPath: \CDArticle.sectionOrder, ascending: true)]         request.predicate = [ICPredicate.fetched].andPredicate()         return request     } } struct ContentView: View {     @Environment(\.managedObjectContext) private var viewContext     @ObservedObject var controller = ArticleController.shared     @SectionedFetchRequest(fetchRequest: CDArticle.displayFetchRequest(),                            sectionIdentifier: \CDArticle.sectionFolder,                            transaction: Transaction(animation: .spring()))     private var fetchedSections     @State var queue = DispatchQueue.global(qos: .userInitiated)     init() {         detach {             await FolderFetcher.shared.fectchNewSections()         }     }     var body: some View {         ScrollViewReader { scrollProxy in             List {                 ForEach(fetchedSections) { section in                     Section(header: Text(FolderFetcher.getSectionName(section.id ?? "Nil") ?? "Nil")) {                         ForEach(section) { article in                             ArticleView(article: article)                                 .setLocationReaderKey(id: article.googleID!)                                 .id(article.googleID)                                 .onAppear {                                     if let topArticleID = topMostArticle {                                         scrollProxy.scrollTo(topArticleID, anchor: .top)                                     }                                 }                         }                     }                 }             }         }     } }
0
0
576
Jun ’21