Yes, after scheduling NSStream in RunLoop its reference count grows. I think that this code is enough to prove it:
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));
And console output:
Stream retain count A is 1
Stream retain count B is 1
Stream retain count C is 3
Stream retain count D is 2
So adding to NSRunLoop increases number references by 2. After nullification of original strong reference counter value remains positive, and this prevents deallocation of stream object.
Because object still exist, will respond to this code:
[(__bridge const NSInputStream*)val.pointerValue open];
[(__bridge const NSInputStream*)val.pointerValue close];
But next line will cause crash - now stream is removed from NSRunLoop. All references to it was removed - what remains is value of pointer to - now deallocated - object (behaves similarly to assigned
pointer). Call to deallocated object always means EXC_BAD_ACCESS
...
NSLog(@"Stream retain count E is %ld",
CFGetRetainCount(val.pointerValue));//crash here