首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >调试核心数据__NSCFSet addObject无异常

调试核心数据__NSCFSet addObject无异常
EN

Stack Overflow用户
提问于 2016-01-07 15:10:09
回答 3查看 6.3K关注 0票数 11

在带有以下消息的Core数据线程上,在单元测试期间引发异常:

CoreData:错误:严重的应用程序错误。在核心数据更改处理过程中捕获了异常。这通常是NSManagedObjectContextObjectsDidChangeNotification.观察者中的一个bug。-__NSCFSet addObject::尝试用userInfo插入零(null)

代码语言:javascript
运行
复制
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFSet addObject:]: attempt to insert nil'
*** First throw call stack:
(
    0   CoreFoundation                      0x00683a14 __exceptionPreprocess + 180
    1   libobjc.A.dylib                     0x02334e02 objc_exception_throw + 50
    2   CoreFoundation                      0x0068393d +[NSException raise:format:] + 141
    3   CoreFoundation                      0x005595b9 -[__NSCFSet addObject:] + 185
    4   CoreData                            0x001d47c0 -[NSManagedObjectContext(_NSInternalChangeProcessing) _processPendingInsertions:withDeletions:withUpdates:] + 560
    5   CoreData                            0x001cee8a -[NSManagedObjectContext(_NSInternalChangeProcessing) _processRecentChanges:] + 2410
    6   CoreData                            0x001ce506 -[NSManagedObjectContext processPendingChanges] + 54
    7   CoreData                            0x001f359b developerSubmittedBlockToNSManagedObjectContextPerform + 443

我正在试图确定是什么导致了它,但是由于它发生在一个NSManagedObjectContext队列上,所以线程在我自己的代码中没有堆栈跟踪。

我在-[__NSCFSet addObject:]-[NSManagedObjectContext processPendingChanges]上设置了符号断点,但在停止时无法看到任何状态,从而帮助我确定哪些对象导致问题。

我想到的下一步是尝试使用swizzling -[__NSCFSet addObject:]来添加我自己的实现,这样我只能在参数为零时停止。希望集合不是空的,我可以在插入零之前看到它的内容来获得更多的信息。不过,我在这门课上遇到了困难,因为这是一门私人课。

使用上面的方法,或者我没有考虑过的方法,我如何才能获得导致异常的更多信息?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-01-15 19:29:13

感谢@bteapot建议我将-com.apple.CoreData.ConcurrencyDebug 1参数添加到我的计划中。我从Ole Begemann出色的核心数据并发调试文章中获得了更多关于这方面工作方式的信息。

添加此标志会在代码从不正确的线程调用到NSManagedObjectContext时立即引发异常。这在Xcode中非常有用,但请注意,在Xcode Bot中,这会导致测试失败,而这则消息毫无帮助:

失去与测试管理器服务的连接

票数 20
EN

Stack Overflow用户

发布于 2018-01-31 03:21:24

我今天也遇到了同样的问题,整天都在为它奋斗。添加并发调试对我来说是一个正确的步骤,但根本的问题是,我试图从不同的线程访问托管对象上下文的同一个实例。导致我崩溃的方法是试图返回一个获取的对象。我能够通过将do、try、catch块包装在context.perform块中来修复它,并使该方法将转义闭包作为参数,而不是返回对象。

代码语言:javascript
运行
复制
func fetchUser(id: Int, completion: @escaping (User) -> ()) {
    let predicate = NSPredicate(format: "id = %d", id)
    let request: NSFetchRequest<User> = User.fetchRequest()
    request.predicate = predicate
    context.perform {
        // try to fetch user from core data
        do {
            if let user = try self.context.fetch(request).first {
                completion(user)
            } else {
                // if no user exists with that id, create and return a new user
                self.seedAutoPopulatingLists(for: id)
                completion(NSEntityDescription.insertNewObject(forEntityName: "User", into: self.context) as! User)
            }
        } catch let error as NSError {
            print("Could not fetch: \(error) \(error.userInfo)")
        }
    }
}

希望这能帮助将来遇到这种情况的人。

票数 1
EN

Stack Overflow用户

发布于 2019-07-23 05:11:36

轻快地5

创建持久性容器

代码语言:javascript
运行
复制
private final class PersistanceContainerProvider  {
    var container: NSPersistentContainer = {
        let container = NSPersistentContainer(name: "Test")
        container.loadPersistentStores(completionHandler: { storeDescription, error in
            if let error = error as NSError? {
                fatalError("Unable to load persistance store")
            }
        })
        return container
    }()
}

创建具有后台并发性的ManagedContext

代码语言:javascript
运行
复制
private init(persistentContainerProvider: DefaultPersistanceContainerProvider = PersistanceContainerProvider()){
        self.persistentContainer = persistentContainerProvider.container
        self.managedObjectContext = persistentContainer.newBackgroundContext()
        print("Wasim \(self.managedObjectContext.concurrencyType.rawValue)")
    }

应用managedObjectContext.performAndWait

代码语言:javascript
运行
复制
func addTargetCode(symbol: Symbol) {
        managedObjectContext.performAndWait {
        do {
            if let existing = try managedObjectContext.fetch(ManagedTargetCurrency.fetchRequest(by: symbol.code)).first {
                existing.code = symbol.code
                existing.name = symbol.name
                 try save()
            } else {
                let added = (NSEntityDescription.insertNewObject(forEntityName: ManagedTargetCurrency.entityName, into: managedObjectContext) as? ManagedTargetCurrency).require(hint: "Wrong Core Data Configuration?")
                added.code = symbol.code
                added.name = symbol.name
                 try save()
            }
        } catch let error {
            print(Errors.addError(cause: error))
        }
        }
    }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34658592

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档