- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
示范
- (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 when it become YES
逻辑被封装得很好,让我可以自由地做额外的 KVO 观察,没有任何问题:
1) 我做了几个测试,表明 NSOperation 在其 -[NSOperation init]
中对属性更改观察进行了某种神奇的订阅 - 我不知道 是什么那里正在进行,但我已确保它与“isFinished->completionBlock”相关的东西正在那里。我想知道除了常见的 -[NSObject init] 逻辑之外还做了什么?
2) NSLog 输出显示它不是 NSOperation 类,而是一些神秘的 NSOperationInternal 被调用了 observeValueForKeyPath:ofObject:changeKind:oldValue:newValue:indexes:context:
最终调用了 completionBlock。
3) 就我的理解而言,GNUStep implementation of NSOperation在实现细节上有所不同(至少在描述的 isFinished-completionBlock
方面,参见,例如 _finish method),这就是为什么我不能用它作为帮助来理解 Apple 的方法NSOperation是怎么写的。
注意
我没有任何 Unresolved 问题,我只是想在isFinished observing -> completionBlock invocation
方面更深入地了解NSOperation内部是如何工作的。
我不想看到:“Apple 的内部是隐藏的,非 Apple 工程师不可能知道”。我希望看到一个确实包含对该主题的深刻见解的答案。
最佳答案
这是我目前对 NSOperation 生命周期的了解,虽然不多,但足以回答我最初的问题:
NSOperation 在它的 -init 方法中注册了它的 isFinished
属性的 KVO 观察。这意味着即使我从未运行过 -start
(main
) 方法(我对自定义 NSOperation 子类进行了一些实验以确定这一点),也会记录观察结果。相应的注销是在 NSOperation 的 -dealloc
方法中完成的(我无法证明这一点,但它确实是唯一可以发生的地方)。
为了使 KVO 成为可能并且“私有(private)”NSOperation 有一些内部容器类 NSOperationInternal,它封装了 NSOperation 的自己的 KVO 例程,让我可以自由地做我的自定义 KVO,当我想为我的 NSOperation 类的自定义子类的实例。在我自定义的 NSOperation 子类中,我可以使用我自己的 observeValueForKeyPath:ofObject:change:context:
方法实现,而不用担心与 NSOperation 自己的 KVO 有任何可能的冲突,因为它不会干扰在 NSOperationInternal 中实现的这个方法。
P.S. 关于“魔法”这个词——我知道幕后都是 KVO——所以这里对 KVO 本身并不感到惊讶。我惊讶的是 KVO 在具体细节上是如何应用于 NSOperation 的:这里没有什么神奇的东西,但它并不是很明显,当我第一次开始引入我自己的 KVO 并对可能的干扰产生怀疑时。
关于objective-c - NSOperation 内部的魔力——它如何观察 isFinished 键以便 completionBlock 始终运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17910902/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!