2016-10-05 2 views
1

Je souhaite envoyer et recevoir des données à l'aide de nsstreams. Je ne veux pas tellement encombrer mon code, donc je me demandais:Est-ce que [NSStream scheduleInRunLoop: forMode:] conserve NSStream?

Dois-je garder une référence forte à un NSStream ou est-ce que [NSStream scheduleInRunLoop: forMode:] crée une référence forte à ce sujet?

Je n'ai trouvé aucune documentation là-dessus. J'ai essayé, et cela fonctionne sans avoir une forte référence.

J'espérais que quelqu'un puisse confirmer ou réfuter cette découverte.

Répondre

1

Oui, après la planification de NSStream dans RunLoop, son nombre de références augmente. Je pense que ce code est suffisant pour prouver:

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)); 

Et la sortie de la console:

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

Ainsi, en ajoutant à NSRunLoop augmente les références numériques par 2. Après l'annulation de la contre-valeur de référence forte originale reste positive, et cela empêche la désallocation de l'objet stream.

Parce que l'objet existe encore, répondra à ce code:

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

Mais la prochaine ligne causera accident - Il est maintenant retiré de flux NSRunLoop. Toutes les références à cela ont été supprimées - ce qui reste est la valeur de pointeur vers - maintenant désalloué - objet (se comporte de manière similaire au pointeur assigned). Appel à l'objet désalloué signifie toujours EXC_BAD_ACCESS ...

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

Vous pouvez également trouver une analogie avec le comportement de NSTimer après avoir ajouté à NSRunLoop. NSTimer a la méthode 'invalidate' pour retirer de NSRunLoop. L'équivalent de NSStream est 'close' –