Wednesday, January 31, 2024
HomeiOS Developmentios - Cannot add second baby to guardian in CoreData

ios – Cannot add second baby to guardian in CoreData


As I struggled with growing my utility I made a decision to study some fundamentals and created playground mission utilizing Core Information in SwiftUI, however I encountered downside I am unable to resolve and even root trigger. Let me start with describing what I attempted to attain and what the issue is.

I created 3 fashions:

  • ListEntity – have identify and to-many relationship to ListItemEntity
  • ListItemEntity – has simply flag and a pair of to-one relationship to ListEntity and NameEntity
  • NameEntity – has simply identify and to-many relationship to ListItemEntity

For these fashions I created 3 primary views to indicate and add knowledge. Views for exhibiting and including ListEntity (first for listing of them and second with their particulars) works wonderful with none downside. The issue I’ve is with third view which consists of searchable listing of NameEntity (with add button, which simply add new NameEntity of identify Title <counts of names>). Every NameEntity row in listing is clickable and by clicking it it’s best to add (or delete) ListItemEntity to at the moment edited ListEntity with chosen NameEntity. That works wonderful so long as you add just one merchandise. When I attempt to add one other I get error someplace in context save methodology. The issue is, my save methodology is inside do { } catch { } block and it ought to print error to console, however as an alternative it crashes entire utility.

Right here is error I am getting:

error: Severe utility error.  Exception was caught throughout Core Information change processing.  That is often a bug inside an observer of NSManagedObjectContextObjectsDidChangeNotification.  -[NameEntity compare:]: unrecognized selector despatched to occasion 0x600002118ff0 with userInfo (null)

With name stack:

*** First throw name stack:

(

0   CoreFoundation                      0x0000000180491128 __exceptionPreprocess + 172

1   libobjc.A.dylib                     0x000000018008412c objc_exception_throw + 56

2   CoreFoundation                      0x00000001804a5f78 +[NSObject(NSObject) instanceMethodSignatureForSelector:] + 0

3   CoreFoundation                      0x0000000180495278 ___forwarding___ + 1280

4   CoreFoundation                      0x000000018049759c _CF_forwarding_prep_0 + 92

5   Basis                          0x0000000180dde258 _NSCompareObject + 60

6   CoreData                            0x00000001863c8564 +[NSFetchedResultsController _insertIndexForObject:inArray:lowIdx:highIdx:sortDescriptors:] + 220

7   CoreData                            0x00000001863c82b4 -[NSFetchedResultsController _updateFetchedObjectsWithInsertChange:] + 832

8   CoreData                            0x00000001863c9e00 __82-[NSFetchedResultsController(PrivateMethods) _core_managedObjectContextDidChange:]_block_invoke + 2364

9   CoreData                            0x0000000186369e80 developerSubmittedBlockToNSManagedObjectContextPerform + 156

10  CoreData                            0x0000000186369d5c -[NSManagedObjectContext performBlockAndWait:] + 212

11  CoreData                            0x00000001863c94a8 -[NSFetchedResultsController _core_managedObjectContextDidChange:] + 96

12  CoreFoundation                      0x00000001803c1878 __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 140

13  CoreFoundation                      0x00000001803c179c ___CFXRegistrationPost_block_invoke + 84

14  CoreFoundation                      0x00000001803c0c8c _CFXRegistrationPost + 404

15  CoreFoundation                      0x00000001803c0668 _CFXNotificationPost + 688

16  Basis                          0x0000000180d84cb4 -[NSNotificationCenter postNotificationName:object:userInfo:] + 88

17  CoreData                            0x000000018635ce54 -[NSManagedObjectContext _postObjectsDidChangeNotificationWithUserInfo:] + 320

18  CoreData                            0x000000018636f640 -[NSManagedObjectContext _createAndPostChangeNotification:deletions:updates:refreshes:deferrals:wasMerge:] + 1244

19  CoreData                            0x000000018635eb9c -[NSManagedObjectContext _processRecentChanges:] + 2884

20  CoreData                            0x0000000186360cc0 -[NSManagedObjectContext save:] + 340

21  Playground                          0x00000001024b8da8 $sSo22NSManagedObjectContextC10PlaygroundE12saveIfNeededyyKF + 108

22  Playground                          0x00000001024b8eac $sSo22NSManagedObjectContextC10PlaygroundE9forceSaveyyF + 60

23  Playground                          0x00000001024c3d30 $s10Playground8NameTileV4bodyQrvgyycfU_ + 1220

24  SwiftUI                             0x00000001c5908800 OUTLINED_FUNCTION_11 + 620

25  SwiftUI                             0x00000001c58365c0 OUTLINED_FUNCTION_31 + 1824

26  SwiftUI                             0x00000001c51f742c OUTLINED_FUNCTION_21 + 32

27  SwiftUI                             0x00000001c4f04840 OUTLINED_FUNCTION_2 + 6392

28  SwiftUI                             0x00000001c4f0c7c4 OUTLINED_FUNCTION_2 + 39036

29  SwiftUI                             0x00000001c51f742c OUTLINED_FUNCTION_21 + 32

30  SwiftUI                             0x00000001c51f7448 OUTLINED_FUNCTION_21 + 60

31  SwiftUI                             0x00000001c51f742c OUTLINED_FUNCTION_21 + 32

32  SwiftUI                             0x00000001c58f6554 OUTLINED_FUNCTION_17 + 2340

33  SwiftUI                             0x00000001c58f6b18 OUTLINED_FUNCTION_17 + 3816

34  SwiftUI                             0x00000001c51e3f04 OUTLINED_FUNCTION_7 + 9760

35  SwiftUI                             0x00000001c51e9298 OUTLINED_FUNCTION_7 + 31156

36  UIKitCore                           0x0000000184a3583c -[UICollectionView _selectItemAtIndexPath:animated:scrollPosition:notifyDelegate:deselectPrevious:performCustomSelectionAction:] + 1176

37  UIKitCore                           0x0000000184a650b4 -[UICollectionView touchesEnded:withEvent:] + 452

38  UIKitCore                           0x000000018531a718 forwardTouchMethod + 264

39  UIKitCore                           0x000000018531a718 forwardTouchMethod + 264

40  UIKitCore                           0x000000018531a718 forwardTouchMethod + 264

41  UIKitCore                           0x0000000184e30458 _UIGestureEnvironmentUpdate + 5912

42  UIKitCore                           0x0000000184e2ea60 -[UIGestureEnvironment _deliverEvent:toGestureRecognizers:usingBlock:] + 288

43  UIKitCore                           0x0000000184e2e7d0 -[UIGestureEnvironment _updateForEvent:window:] + 156

44  UIKitCore                           0x0000000185329f00 -[UIWindow sendEvent:] + 3088

45  UIKitCore                           0x000000018530998c -[UIApplication sendEvent:] + 576

46  UIKitCore                           0x000000018538a5c0 __dispatchPreprocessedEventFromEventQueue + 1708

47  UIKitCore                           0x000000018538d474 __processEventQueue + 5524

48  UIKitCore                           0x0000000185385e38 __eventFetcherSourceCallback + 156

49  CoreFoundation                      0x00000001803f1f18 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24

50  CoreFoundation                      0x00000001803f1e60 __CFRunLoopDoSource0 + 172

51  CoreFoundation                      0x00000001803f15d0 __CFRunLoopDoSources0 + 232

52  CoreFoundation                      0x00000001803ebcb8 __CFRunLoopRun + 768

53  CoreFoundation                      0x00000001803eb5a4 CFRunLoopRunSpecific + 572

54  GraphicsServices                    0x000000018e9fbae4 GSEventRunModal + 160

55  UIKitCore                           0x00000001852f02e4 -[UIApplication _run] + 868

56  UIKitCore                           0x00000001852f3f5c UIApplicationMain + 124

57  SwiftUI                             0x00000001c51fc1b0 OUTLINED_FUNCTION_70 + 500

58  SwiftUI                             0x00000001c51fc050 OUTLINED_FUNCTION_70 + 148

59  SwiftUI                             0x00000001c4f02fa4 OUTLINED_FUNCTION_2 + 92

60  Playground                          0x00000001024c9598 $s10Playground0A3AppV5$mainyyFZ + 40

61  Playground                          0x00000001024c9648 primary + 12

62  dyld                                0x0000000102655544 start_sim + 20

63  ???                                 0x00000001028660e0 0x0 + 4337328352

64  ???                                 0xc719000000000000 0x0 + 14346498087965425664

)

Now right here is my code, beginning with knowledge definition first:

<?xml model="1.0" encoding="UTF-8" standalone="sure"?>

<mannequin kind="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="22522" systemVersion="23C71" minimumToolsVersion="Automated" sourceLanguage="Swift" usedWithSwiftData="YES" userDefinedModelVersionIdentifier="">

<entity identify="ListEntity" representedClassName="ListEntity" syncable="YES">

<attribute identify="identify" non-obligatory="YES" attributeType="String"/>

<relationship identify="gadgets" non-obligatory="YES" toMany="YES" deletionRule="Cascade" destinationEntity="ListItemEntity" inverseName="listing" inverseEntity="ListItemEntity"/>

</entity>

<entity identify="ListItemEntity" representedClassName="ListItemEntity" syncable="YES">

<attribute identify="flag" non-obligatory="YES" attributeType="Boolean" usesScalarValueType="YES"/>

<relationship identify="listing" non-obligatory="YES" maxCount="1" deletionRule="Nullify" destinationEntity="ListEntity" inverseName="gadgets" inverseEntity="ListEntity"/>

<relationship identify="identify" non-obligatory="YES" maxCount="1" deletionRule="Nullify" destinationEntity="NameEntity" inverseName="gadgets" inverseEntity="NameEntity"/>

</entity>

<entity identify="NameEntity" representedClassName="NameEntity" syncable="YES">

<attribute identify="identify" non-obligatory="YES" attributeType="String"/>

<relationship identify="gadgets" non-obligatory="YES" toMany="YES" deletionRule="Nullify" destinationEntity="ListItemEntity" inverseName="identify" inverseEntity="ListItemEntity"/>

</entity>

</mannequin>
class DataProvider {
    static let shared = DataProvider()
    personal let container: NSPersistentContainer

    var viewContext: NSManagedObjectContext {
        container.viewContext
    }

    personal init() {
        container = NSPersistentContainer(identify: "Information")
        container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
        container.loadPersistentStores { description, error in
            print(description.url?.path(percentEncoded: false) ?? "No URL")
            if let error {
                fatalError("Couldn't load persistent shops: (error.localizedDescription)")
            }
        }
        container.viewContext.automaticallyMergesChangesFromParent = true
        container.viewContext.mergePolicy = NSMergePolicy.mergeByPropertyObjectTrump
    }
}

extension NSManagedObjectContext {
    func saveIfNeeded() throws {
        guard hasChanges else { return }
        attempt save()
    }

    func forceSave() {
        do {
            attempt saveIfNeeded()
        } catch {
            print(error.localizedDescription)
        }
    }
}

@objc(ListEntity)
public class ListEntity: NSManagedObject {}

public extension ListEntity {
    @nonobjc class func fetchRequest() -> NSFetchRequest<ListEntity> {
        NSFetchRequest<ListEntity>(entityName: "ListEntity")
    }

    @NSManaged var identify: String?
    @NSManaged var gadgets: NSSet?

    var wrappedName: String {
        identify ?? "No identify"
    }

    var wrappedItems: [ListItemEntity] {
        if let gadgets = gadgets as? Set<ListItemEntity> {
            return gadgets.sorted(utilizing: KeyPathComparator(.wrappedName))
        }
        return []
    }
}

// MARK: Generated accessors for gadgets

public extension ListEntity {
    @objc(addItemsObject:)
    @NSManaged func addToItems(_ worth: ListItemEntity)

    @objc(removeItemsObject:)
    @NSManaged func removeFromItems(_ worth: ListItemEntity)

    @objc(addItems:)
    @NSManaged func addToItems(_ values: NSSet)

    @objc(removeItems:)
    @NSManaged func removeFromItems(_ values: NSSet)
}

extension ListEntity: Identifiable {}

@objc(ListItemEntity)
public class ListItemEntity: NSManagedObject {}

public extension ListItemEntity {
    @nonobjc class func fetchRequest() -> NSFetchRequest<ListItemEntity> {
        NSFetchRequest<ListItemEntity>(entityName: "ListItemEntity")
    }

    @nonobjc class func fetchRequestFor(_ listing: ListEntity, sortDescriptors: [NSSortDescriptor] = []) -> NSFetchRequest<ListItemEntity> {
        let fetchRequest = Self.fetchRequest()
        fetchRequest.predicate = NSPredicate(format: "listing == %@", listing)
        fetchRequest.sortDescriptors = sortDescriptors
        return fetchRequest
    }

    @nonobjc class func fetchRequest(with identify: NameEntity, on listing: ListEntity, sortDescriptors: [NSSortDescriptor] = []) -> NSFetchRequest<ListItemEntity> {
        let fetchRequest = Self.fetchRequest()
        fetchRequest.predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [
            NSPredicate(format: "list == %@", list),
            NSPredicate(format: "name == %@", name),
        ])
        fetchRequest.sortDescriptors = sortDescriptors
        return fetchRequest
    }

    @NSManaged var flag: Bool
    @NSManaged var listing: ListEntity?
    @NSManaged var identify: NameEntity?

    var wrappedName: String {
        identify?.wrappedName ?? "No identify"
    }
}

extension ListItemEntity: Identifiable {}

@objc(NameEntity)
public class NameEntity: NSManagedObject {}

public extension NameEntity {
    @nonobjc class func fetchRequest() -> NSFetchRequest<NameEntity> {
        NSFetchRequest<NameEntity>(entityName: "NameEntity")
    }

    @nonobjc class func fetchRequest(containing identify: String, fetchLimit: Int? = nil, sortDescriptors: [NSSortDescriptor] = []) -> NSFetchRequest<NameEntity> {
        let fetchRequest = Self.fetchRequest()
        if let fetchLimit {
            fetchRequest.fetchLimit = fetchLimit
        }
        let trimmedName = identify.trimmingCharacters(in: .whitespacesAndNewlines)
        if !trimmedName.isEmpty {
            fetchRequest.predicate = NSPredicate(format: "identify CONTAINS[cd] %@", trimmedName)
        }
        fetchRequest.sortDescriptors = sortDescriptors
        return fetchRequest
    }

    @NSManaged var identify: String?
    @NSManaged var gadgets: NSSet?

    var wrappedName: String {
        identify ?? "No identify"
    }

    var wrappedItems: [ListItemEntity] {
        if let gadgets = gadgets as? Set<ListItemEntity> {
            return gadgets.sorted(utilizing: KeyPathComparator(.wrappedName))
        }
        return []
    }
}

// MARK: Generated accessors for gadgets

public extension NameEntity {
    @objc(addItemsObject:)
    @NSManaged func addToItems(_ worth: ListItemEntity)

    @objc(removeItemsObject:)
    @NSManaged func removeFromItems(_ worth: ListItemEntity)

    @objc(addItems:)
    @NSManaged func addToItems(_ values: NSSet)

    @objc(removeItems:)
    @NSManaged func removeFromItems(_ values: NSSet)
}

extension NameEntity: Identifiable {}

Lastly my Views:

struct ListEntitiesView: View {
    @Surroundings(.managedObjectContext)
    personal var viewContext
    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: ListEntity.name, ascending: true)],
        animation: .default
    )
    personal var lists: FetchedResults<ListEntity>

    var physique: some View {
        NavigationStack {
            Checklist {
                ForEach(lists) { listing in
                    NavigationLink(worth: listing) {
                        ListEntityTile(listing)
                    }
                }
            }
            .navigationTitle("ListEntities")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                Button {
                    let listing = ListEntity(context: viewContext)
                    listing.identify = "Checklist (lists.depend + 1)"
                    viewContext.forceSave()
                } label: {
                    Label("Add Checklist", systemImage: "plus")
                }
            }
            .navigationDestination(for: ListEntity.self) { listing in
                ListEntityView(listing)
            }
        }
    }
}

struct ListEntityTile: View {
    @ObservedObject
    personal var listing: ListEntity
    @FetchRequest
    personal var gadgets: FetchedResults<ListItemEntity>

    personal var totalItems: Int {
        gadgets.depend
    }

    personal var flaggedItems: Int {
        gadgets.filter(.flag).depend
    }

    init(_ listing: ListEntity) {
        _list = ObservedObject(wrappedValue: listing)
        _items = FetchRequest(fetchRequest: ListItemEntity.fetchRequestFor(listing))
    }

    var physique: some View {
        HStack {
            Textual content(listing.wrappedName)
            Spacer()
            Textual content("(flaggedItems) / (totalItems)")
        }
    }
}

struct ListEntityView: View {
    @Surroundings(.managedObjectContext)
    personal var viewContext
    @ObservedObject
    personal var listing: ListEntity
    @FetchRequest
    personal var gadgets: FetchedResults<ListItemEntity>

    init(_ listing: ListEntity) {
        _list = ObservedObject(wrappedValue: listing)
        _items = FetchRequest(fetchRequest: ListItemEntity.fetchRequestFor(listing, sortDescriptors: [NSSortDescriptor(keyPath: ListItemEntity.name, ascending: true)]))
    }

    var physique: some View {
        Checklist {
            ForEach(gadgets) { merchandise in
                ListItemTile(merchandise)
            }
        }
        .navigationTitle(listing.wrappedName)
        .navigationBarTitleDisplayMode(.inline)
        .toolbar {
            NavigationLink {
                AddListItemEntity(listing)
            } label: {
                Label("Add Merchandise", systemImage: "plus")
            }
        }
    }
}

struct ListItemTile: View {
    @Surroundings(.managedObjectContext)
    personal var viewContext
    @ObservedObject
    personal var merchandise: ListItemEntity

    init(_ merchandise: ListItemEntity) {
        _item = ObservedObject(wrappedValue: merchandise)
    }

    var physique: some View {
        Button {
            merchandise.flag.toggle()
            viewContext.forceSave()
        } label: {
            Label(merchandise.wrappedName, systemImage: merchandise.flag ? "checkmark.circle" : "circle")
        }
    }
}

struct AddListItemEntity: View {
    @Surroundings(.managedObjectContext)
    personal var viewContext
    @ObservedObject
    personal var listing: ListEntity
    @State
    personal var searchName = ""
    @FetchRequest(sortDescriptors: [])
    personal var names: FetchedResults<NameEntity>

    init(_ listing: ListEntity) {
        _list = ObservedObject(wrappedValue: listing)
    }

    var physique: some View {
        Checklist {
            TextField("Search identify", textual content: $searchName.animation())
            NamesList(for: listing, containing: searchName)
        }
        .toolbar {
            Button {
                let identify = NameEntity(context: viewContext)
                identify.identify = "Title (names.depend + 1)"
                viewContext.forceSave()
            } label: {
                Label("Add Title", systemImage: "plus")
            }
        }
    }
}

struct NamesList: View {
    @ObservedObject
    personal var listing: ListEntity
    @FetchRequest
    personal var names: FetchedResults<NameEntity>

    init(for listing: ListEntity, containing identify: String) {
        _list = ObservedObject(wrappedValue: listing)
        _names = FetchRequest(
            fetchRequest: NameEntity.fetchRequest(containing: identify, sortDescriptors: [NSSortDescriptor(keyPath: NameEntity.name, ascending: true)]),
            animation: .default
        )
    }

    var physique: some View {
        ForEach(names) { identify in
            NameTile(of: identify, for: listing)
        }
    }
}

struct NameTile: View {
    @Surroundings(.managedObjectContext)
    personal var viewContext
    @FetchRequest
    personal var gadgets: FetchedResults<ListItemEntity>
    @ObservedObject
    personal var listing: ListEntity
    @ObservedObject
    personal var identify: NameEntity

    personal var merchandise: ListItemEntity? {
        gadgets.first { $0.identify == identify }
    }

    init(of identify: NameEntity, for listing: ListEntity) {
        _list = ObservedObject(wrappedValue: listing)
        _name = ObservedObject(wrappedValue: identify)
        _items = FetchRequest(
            fetchRequest: ListItemEntity.fetchRequestFor(listing),
            animation: .default
        )
    }

    var physique: some View {
        Button {
            if let merchandise {
                viewContext.delete(merchandise)
            } else {
                let newItem = ListItemEntity(context: viewContext)
                newItem.flag = false
                newItem.identify = identify
                newItem.listing = listing
            }
            viewContext.forceSave()
        } label: {
            Label(identify.wrappedName, systemImage: merchandise != nil ? "checkmark.circle" : "circle")
        }
    }
}

I assumed that I should have someway misconfigured ListItemEntity to ListEntity relationship, however I managed to run this code inside my DataProvider and it labored with none downside:

let listing = ListEntity(context: viewContext)
listing.identify = "Checklist 1"
viewContext.forceSave()
        
var names = [NameEntity(context: viewContext), NameEntity(context: viewContext)]
for identify in names {
    identify.identify = "Title (names.firstIndex(of: identify) ?? 0)"
}
viewContext.forceSave()
        
let gadgets = [ListItemEntity(context: viewContext), ListItemEntity(context: viewContext)]
for merchandise in gadgets {
    merchandise.flag = false
    merchandise.listing = listing
    merchandise.identify = names.popLast()
}
viewContext.forceSave()

I consider it have to be one thing easy and apparent as that is quite simple use case I believe, however my lack of expertise get my to level I am unable to do something greater than ask in your assist.



Supply hyperlink

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisment -
Google search engine

Most Popular

Recent Comments