[NSStream scheduleInRunLoop: forMode:] 是否保留 NSStream?

Does [NSStream scheduleInRunLoop: forMode:] retain the NSStream?

我想使用 nsstreams 发送和接收一些数据。我不想让我的代码如此混乱,所以我想知道:

我是否需要保留对 NSStream 的强引用,或者 [NSStream scheduleInRunLoop: forMode:] 创建对它的强引用?

我找不到任何相关文档。我已经尝试过了,它在没有自己的强参考的情况下也能工作。

我希望有人能证实或反驳这一发现。

是的,在 RunLoop 中调度 NSStream 后,它的引用计数增加了。我认为这段代码足以证明这一点:

NSInputStream* nStream = [[NSInputStream alloc] initWithFileAtPath:path];
NSLog(@"Stream retain count A is %ld", CFGetRetainCount((__bridge CFTypeRef)nStream));
NSValue* val = [NSNumber valueWithPointer:(__bridge const void * _Nullable)(nStream)];// not increment reference counter
NSLog(@"Stream retain count B is %ld", CFGetRetainCount(val.pointerValue));
[nStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
NSLog(@"Stream retain count C is %ld", CFGetRetainCount(val.pointerValue));
nStream = nil;
NSLog(@"Stream retain count D is %ld", CFGetRetainCount(val.pointerValue));

控制台输出:

 Stream retain count A is 1
 Stream retain count B is 1
 Stream retain count C is 3
 Stream retain count D is 2

因此,添加到 NSRunLoop 会使引用数增加 2。原始强引用计数器值无效后仍为正值,这会阻止流对象的重新分配。

因为对象还存在,会响应这个代码:

[(__bridge const NSInputStream*)val.pointerValue open];
[(__bridge const NSInputStream*)val.pointerValue close];

但下一行会导致崩溃 - 现在流已从 NSRunLoop 中删除。所有对它的引用都被删除——剩下的是指针的值——现在被释放——对象(行为类似于 assigned 指针)。调用释放对象总是意味着 EXC_BAD_ACCESS...

NSLog(@"Stream retain count E is %ld",
CFGetRetainCount(val.pointerValue));//crash here