2016-10-05 30 views
1

nsstreams를 사용하여 일부 데이터를 보내고 받고 싶습니다. 내 코드를 너무 복잡하게 만들고 싶지 않아서 궁금 해서요 :[NSStream scheduleInRunLoop : forMode :]가 NSStream을 유지합니까?

NSStream에 대한 강력한 참조를 유지해야합니까? 아니면 [NSStream scheduleInRunLoop : forMode :]가 강력한 참조를 만들고 있습니까?

관련 문서를 찾을 수 없습니다. 나는 노력했고, 자신 만의 강력한 레퍼런스가 없어도 작동한다.

나는 누군가가 그 발견을 확인하거나 반박하기를 바랬다.

답변

1

예, 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 
+0

또한 NSRunLoop에 추가 한 후 NSTimer의 동작과 비유를 찾을 수 있습니다. NSTimer는 NSRunLoop에서 제거하기위한'invalidate' 메소드를 가지고 있습니다. NSStream 해당 사항은'close'입니다. –