Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/amazon-web-services/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c NSOperation内部的魔力-它如何观察isFinished键以便completionBlock始终运行?_Objective C_Nsoperation - Fatal编程技术网

Objective c NSOperation内部的魔力-它如何观察isFinished键以便completionBlock始终运行?

Objective c NSOperation内部的魔力-它如何观察isFinished键以便completionBlock始终运行?,objective-c,nsoperation,Objective C,Nsoperation,演示 - (void)test_NSOperationCallsCompletionBlockWhenFinished { __block BOOL flag = NO; NSOperation *operation = [NSOperation new]; operation.completionBlock = ^{ NSLog(@"Hunting NSOperation internals: %@", [NSThread callStackSymb

演示

- (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是如何根据对
isFinished
属性更改的观察来调用其
completionBlocks
-

我不明白的是,
isFinished
属性的我的观测者从不干扰NSOperation的观测者(如果我添加他们,删除他们…),因此,
observe isFinished->invoke completionBlock(当它变为YES时)
逻辑被很好地封装,使我可以自由地进行额外的KVO观察,而不会出现任何问题:

1) 我做了两个测试,显示NSOperation在其
-[NSOperation init]
-中对属性更改进行了某种神奇的订阅-我不知道那里发生了什么,但我已经确保它与“isFinished->completionBlock”相关。我想知道除了公共-[NSObject init]逻辑之外还有什么其他功能

2) NSLog输出显示,最终调用completionBlock的不是NSOperation类,而是一些神秘的NSOperationInternal,它是通过对象的observeValueForKeyPath:changeKind:oldValue:newValue:indexes:context:调用的

3) 就我的理解而言,实现细节不同(至少在所描述的
isFinished completionBlock
方面,例如,请参见),这就是为什么我不能用它来帮助理解苹果编写NSOperation的方法


N.B.

我没有任何问题没有解决,我只是想在
isFinished->completionBlock invocation
方面更深入地了解NSOperation在内部是如何工作的


我不想看到:“苹果的内部是隐藏的,非苹果工程师不可能知道。”。我想看到一个对这个主题有深刻见解的答案。

这是我目前对NSOperation生命周期的了解,虽然不多,但足以回答我最初的问题:

  • NSOperation在its-init方法中注册其
    isFinished
    属性的KVO观察。这意味着,即使我从未运行过
    -start
    main
    )方法,也会注册观察结果(我使用自定义NSOperation子类做了一些实验来确定这一点)。相应的取消注册是在NSOperation的
    -dealloc
    方法中完成的(我无法证明这一点,但它确实是唯一可以发生这种情况的地方)

  • 为了使KVO成为可能且“私有”,NSOperation有一些内部容器类NSOperationInternal,它封装了NSOperation自己的KVO例程,当我想为NSOperation类的自定义子类的实例实现自定义KVO时,我可以自由地执行自定义KVO。在我的自定义NSOperation子类中,我可以使用自己的
    observeValueForKeyPath:ofObject:change:context:
    方法实现,而不必担心与NSOperation自己的KVO有任何可能的冲突,因为它不会干扰在NSOperationInternal中实现的此方法


  • p.S.关于“魔法”这个词——我知道这都是幕后的KVO——所以这里对KVO本身并不感到惊讶。我感到惊讶的是KVO在具体细节上是如何应用于NSO操作的:这里没有什么神奇之处,但当我第一次开始介绍我自己的KVO并对可能的干扰产生怀疑时,它并不明显。

    不清楚您在问什么。你认为哪一点kvo是“魔法”?到底是什么让你感到惊讶?什么是“魔法订阅”?你说你的isFinished观察员从不干涉NSO的行动。为什么会这样?我刚刚用更多的细节更新了我的问题-请参阅“更多细节…”。你有没有对这个问题的内部运作有过任何启示?目前正在尝试覆盖completionBlock调用,以便它在特定线程上执行,因此一直遵循与您自己类似的路径。请参阅我刚才发布的答案。关于您试图覆盖对
    completionBlock
    的调用,在我看来,您所寻找的与此问题无关。如果您想让您的
    completionBlock
    在另一个线程上执行某些操作,只需在completionBlock中滚动此例程,只需使用-[NSOperation setCompletionBlock:]并在其中编写“另一个线程的代码”。我从未尝试过破解NSOperation的生命周期-我的问题实际上是关于在NSOperation默认值之上的自定义KVO-它不是NSOperation预期行为的替代品!有道理-我自己也在想为什么我对对象:change:context的
    observeValueForKeyPath:的重写没有破坏任何东西。干杯