1

I'm facing a strange behaviour with NSBatchInsertRequest and I don't seems to understand what is causing my problem. I have some piece of code that updates local data depending on some remote data changes. The model that is being updated contains a boolean shared indicating if the item is shared or not. Updating this model seems to work correctly when the boolean goes from false to true but when trying to update the data with the reverse action the new local data doesn't seem to be persisted and I end up having the shared variable always returning true even is the content of the NSBatchInsertRequest has it set as false.

Following are the different parts of my logic and my managed object description.

enter image description here

Helper functions


   func newTaskContext(type: TaskContextType,
                        transactionAuthor: String = #function) -> NSManagedObjectContext {
        let taskContext = container.newBackgroundContext()
        taskContext.name = type.rawValue
        taskContext.transactionAuthor = transactionAuthor
        taskContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
        taskContext.undoManager = nil
        return taskContext
    }

    func newBatchInsertRequest<T>(entity: NSEntityDescription,
                                  sourceItems: [T],
                                  hydrateBlock: @escaping (NSManagedObject, T) -> Void)
        -> NSBatchInsertRequest {
        var index = 0
        let request = NSBatchInsertRequest(entity: entity,
                                           managedObjectHandler: { object in
                                               guard index < sourceItems.count else { return true }
                                               let item = sourceItems[index]
                                               hydrateBlock(object, item)
                                               index += 1
                                               return false
                                           })
        return request
    }

extension ShareEntity {
    func hydrate(from symmetricallyEncryptedShare: SymmetricallyEncryptedShare, userId: String) {
        let share = symmetricallyEncryptedShare.share
        content = share.content
        contentFormatVersion = share.contentFormatVersion ?? -1
        contentKeyRotation = share.contentKeyRotation ?? -1
        createTime = share.createTime
        expireTime = share.expireTime ?? -1
        owner = share.owner
        permission = share.permission
        primary = share.primary
        shareID = share.shareID
        symmetricallyEncryptedContent = symmetricallyEncryptedShare.encryptedContent
        targetID = share.targetID
        targetType = share.targetType
        vaultID = share.vaultID
        addressID = share.addressID
        userID = userId
        shareRoleID = share.shareRoleID
        targetMembers = share.targetMembers
        shared = share.shared
    }
}

    func execute(batchInsertRequest request: NSBatchInsertRequest,
                 context: NSManagedObjectContext) async throws {
        try await context.perform {
            guard context.hasPersistentStore else { return }
            let fetchResult = try context.execute(request)
            if let result = fetchResult as? NSBatchInsertResult,
               let success = result.result as? Bool, success {
                return
            } else {
                throw error
            }
        }
    }

Main local data updating entry point

   func upsertShares(_ shares: [SymmetricallyEncryptedShare], userId: String) async throws {
        let taskContext = newTaskContext(type: .insert)

        let batchInsertRequest =
            newBatchInsertRequest(entity: ShareEntity.entity(context: taskContext),
                                  sourceItems: shares) { managedObject, share in
                (managedObject as? ShareEntity)?.hydrate(from: share, userId: userId)
            }

        try await execute(batchInsertRequest: batchInsertRequest, context: taskContext)
    }

I don't understand why the update of ShareEntity work one way but cannot be updated back to containing the variable shared as false. Any tips or advice would be welcome on this issue.

Martin
  • 843
  • 8
  • 17

0 Answers0