示范
- (void)test_NSOperationCallsCompletionBlockWhenFinished {
__block BOOL flag = NO;
NSOperation *operation = [NSOperation new];
operation.completionBlock = ^{
NSLog(@"Hunting NSOperation internals: %@", [NSThread callStackSymbols]);
flag = YES;
};
[operation start];
while (flag == NO);
STAssertTrue(flag, nil);
}
给我以下输入:
2013-07-28 19:59:44.690 SACompositeOperationsApp[99551:3103] Hunting NSOperation internals: (
0 SACompositeOperationsApp 0x000000010005bbd9 __68-[SAOperationTests test_NSOperationCallsCompletionBlockWhenFinished]_block_invoke + 41
1 Foundation 0x00007fff8a27bb25 __+[__NSOperationInternal _observeValueForKeyPath:ofObject:changeKind:oldValue:newValue:indexes:context:]_block_invoke_3 + 55
2 libdispatch.dylib 0x00007fff8abd9a82 _dispatch_call_block_and_release + 18
3 libdispatch.dylib 0x00007fff8abdb083 _dispatch_async_f_redirect_invoke + 112
4 libdispatch.dylib 0x00007fff8abda961 _dispatch_worker_thread2 + 255
5 libsystem_c.dylib 0x00007fff91ce13da _pthread_wqthread + 316
6 libsystem_c.dylib 0x00007fff91ce2b85 start_wqthread + 13
)
背景
我正在用我的自定义 NSOperation 子类做一些实验——我试图在isFinished
属性上添加我自己的观察者,它们按预期工作得很好。
这些实验让我惊讶于 NSOperation 如何completionBlocks
根据其对isFinished
属性变化的观察来调用它 -
我不明白的事情,这就是为什么这个问题是我的isFinished
财产观察者永远不会干扰 NSOperation 的观察者(如果我添加它们,删除它们......),所以observe isFinished -> invoke completionBlock when it becomes YES
逻辑被很好地封装给我一个自由去做额外的 KVO 观察没有任何问题:
1)我做了一些测试,向我展示了 NSOperation 对属性更改观察进行了某种魔术订阅-[NSOperation init]
- 我不知道那里发生了什么,但我确保它与“isFinished->完成块”去那里。我想知道除了常见的 -[NSObject init] 逻辑之外还做了什么?
2) NSLog 输出显示它不是 NSOperation 类,而是调用了一些神秘的 NSOperationInternal observeValueForKeyPath:ofObject:changeKind:oldValue:newValue:indexes:context:
,最终调用了completionBlock。
3) 就我的理解而言, NSOperation 的 GNUStep 实现在实现细节上有所不同(至少在所描述的isFinished-completionBlock
方面,例如,参见_finish 方法),这就是为什么我不能将它用作帮助了解 Apple 编写 NSOperation 的方法。
注意
我没有任何未解决的问题,我只是想更深入地了解 NSOperation 在isFinished observing -> completionBlock invocation
.
我不想看到:“苹果的内部是隐藏的,不可能被非苹果工程师知道”。我想看到一个包含对该主题的深刻见解的答案。