奇怪的NSSet复制崩溃
我有一个包含NSSet
的类。 这个对象被称为_collectibles
,在一个方法中,我做了一个副本,以便做一些处理,如:
NSSet* collectibleCopy = [_collectibles copy];
在实践中,我看到这个消息经常崩溃:
[__NSPlaceholderSet initWithObjects:count:]: attempt to insert nil object from objects
我通过将上面的代码更改为:
NSMutableSet* collectibleCopy = [[NSMutableSet alloc] initWithCapacity: [_collectibles count]];
for ( id thing in _collectibles ) {
[collectibleCopy addObject: thing];
}
现在我再也不能再现这样的崩溃了。 我打赌[copy]
效率更高,我宁愿使用它,但我无法弄清楚为什么它是完全不可靠的!
更新:虽然完整的上下文需要大量的解释,但我解决这个问题的关键是,a,代码是这样调用的:
NSBlockOperation* operation = [NSBlockOperation blockOperationWithBlock: ^{
[thing doStuff];
}];
[operationQueue addOperation: operation];
我的意思是,基本上是通过减慢一些事情,使用2个线程运行2个线程来捕获应用程序,从而初始化一个队列:
operationQueue.maxConcurrentOperationCount = 1;
我认为不可能。 线索是第二个线程在[NSAutoreleasePool drain]中,这让我了解到NSOperationQueue可以在任何时候/无论它想要什么时候执行autorelease。
将
NSSet* collectibleCopy = [NSSet setWithSet:_collectibles]
为你工作?
好吧,真的很想知道这件事。
这里的诀窍是这个操作是在一个异步NSOperationQueue
上执行的。 TIL表示NSOperationQueues拥有AutoreleasePools,但是他们会根据GCD的判断将其耗尽。 在这种情况下,来自先前操作的池正在另一个线程上同时耗尽,导致相当不透明的并发修改问题。
解:
@autoreleasepool
在代码被调用的块内部。 这会导致排水作为块的一部分发生,而不是异步发生,并且我的比赛状况消失。
上一篇: Bizarre NSSet copying crash
下一篇: How to pass parameter to Microsoft Sync 2.1 generated Stored procedures