La faiblesse de la NSString variable n'est pas nul, après le réglage de la seule référence forte à néant
J'ai un problème avec ce code :
__strong NSString *yourString = @"Your String";
__weak NSString *myString = yourString;
yourString = nil;
__unsafe_unretained NSString *theirString = myString;
NSLog(@"%p %@", yourString, yourString);
NSLog(@"%p %@", myString, myString);
NSLog(@"%p %@", theirString, theirString);
J'attends tous les pointeurs être nil
à ce moment, mais ils ne le sont pas et je ne comprends pas pourquoi.
La première (fort) pointeur est nil
mais les deux autres ne le sont pas. Pourquoi est-ce?
OriginalL'auteur marcL | 2012-06-06
Vous devez vous connecter pour publier un commentaire.
tl; dr: Le problème est que le littéral de chaîne n'est jamais publié de sorte que votre faible pointeur pointe toujours vers elle.
Théorie
Forte variables de conserver la valeur qu'ils pointent.
Faible variables de ne pas conserver leur valeur, et lorsque la valeur est libérée, ils établissent leurs pointeur à zéro (pour être sûr).
Dangereux consignes valeurs (comme vous pouvez probablement lu par le nom) ne conserve pas la valeur, et si il est libéré, ils ne font rien à ce sujet, potentiellement pointant vers un mauvais morceau de mémoire
Littéraux et les constantes
Lorsque vous créez une chaîne à l'aide de
@"literal string"
il devient un littéral de chaîne qui ne le sera jamais changer. Si vous utilisez la même chaîne, dans de nombreux endroits dans votre application, il est toujours le même objet. Les littéraux de chaîne ne va pas loin. À l'aide de[[NSString alloc] initWithString:@"literal string"]
ne fera pas une différence. Puisqu'il devient un pointeur vers la chaîne littérale. Il est toutefois intéressant de noter que[[NSString alloc] initWithFormat:@"literal string"];
fonctionne différemment et la libération de son objet string.Ligne par ligne:
Vous êtes à la création d'une forte pointeur vers une chaîne de caractères. Cela permettra d'assurer que la valeur ne va pas loin. Dans votre cas, c'est un peu spécial puisque la chaîne est une chaîne de caractères littérale que, techniquement, ne pourra pas être diffusé.
Vous créez un faible pointeur de la même chose que votre forte pointeur. Si à ce moment la forte pointeur pointant à quelque chose d'autre, de la valeur, il est de pointage pour les désallouées, puis la faiblesse du pointeur de modifier sa valeur, de sorte qu'il pointe vers
nil
. Maintenant, il pointe toujours à la même chose que la forte pointeur.Votre forte d'un pointeur sur
nil
. Rien de points à l'ancienne chaîne de sorte qu'il devrait sortir si ce n'était pas pour le fait que c'était un littéral de chaîne. Si vous avez essayé la même chose avec les autres objets que vous avez créés vous-même, la faiblesse de la variable de changement, de sorte qu'il pointe versnil
. Mais, depuis la chaîne littérale est littérale et ne va pas loin. La faiblesse de la variable sera toujours point.Une nouvelle consignes pointeur est créé, pointant vers votre faible pointeur qui pointe vers la chaîne de caractères littérale.
Vous imprimez tous vos cordes et se confondre pourquoi la première valeur est
nil
mais les deux autres ne le sont pas.Liées à la lecture:
Quelle est la différence entre une chaîne de caractères constante et d'une chaîne de caractères littérale?
Désolé, aucun. Qui sera aussi le point de la chaîne de caractères littérale qui signifie que la faiblesse du pointeur lors du pointage de la forte pointeur pointe vers la chaîne de caractères littérale qui ne va pas loin.
Oh, j'ai essayé d'initialisation YourString avec cette fonction initWithUTF8String et le résultat a été bon. Juste une dernière question, pour quelle raison, ce n'est pas possible d'obtenir le même résultat avec : "initWithString" ?
Désolé, je ne serai pas en mesure de donner une bonne réponse à pourquoi. C'est juste la façon dont les choses fonctionnent. Je ne peux que deviner pourquoi initWithUTF8String fonctionne différemment, mais c'est juste mes suppositions.
C'est un détail d'implémentation, mais
-initWithString:
est fondamentalement libérant l'objet sur lequel elle est appelée, la copie de l'argument, et le retour de cette copie. Comme une autre optimisation, immuable valeur des objets souvent de mettre en œuvre-copy
de faire juste un-retain
parce qu'il n'a pas d'importance si vous avez une copie "réelle" ou tout simplement obtenir le même objet nouveau. Depuis l'origine est immuable et la copie sera immuable, ils seront toujours les mêmes. Enfin, tout en conservant un littéral de chaîne ne fait rien car elle est permanente. Le tout combiné,-initWithString:
, donné un littéral, renvoie la même littéral.OriginalL'auteur David Rönnqvist
David est correct à 100% dans sa réponse. J'ai juste ajouté quatre des exemples explicites à l'aide de GHUnit.
La durée de vie du qualificatif de comportement pour les références de l'objet.
À l'aide de
NSObject
comme un proxy pour tous les objets, le comportement de la durée de vie qualificatifs est comme prévu.La durée de vie du qualificatif de comportement pour littérale
NSString
s (@"quelque chose").C'est essentiellement la même que
test_usingNSObjects
, mais au lieu d'utiliser unNSObject
, unNSString
qui est attribué un littéral de chaîne est utilisée. Depuis les chaînes littérales ne sont pas détruits comme les autres objets, des comportements différents pour__weak
et__unsafe_unretained
variables sont observées.La durée de vie de qualifier le comportement de non littérale
NSString
s.C'est essentiellement la même que
test_usingNSObjects
, mais au lieu d'utiliser unNSObject
, unNSString
qui est attribué un non littéral de chaîne est utilisé. Depuis le non littérale chaînes sont détruits comme les autres objets, les comportements sont les mêmes que ceux observés danstest_usingNSObjects
.NSString
création littérale vs non littéral.Montre les chaînes créées dans les différentes façons si ils sont littéral, ni non littéral.
OriginalL'auteur mmorris
la faiblesse de la propriété ne sera définie à zéro après l'autorelease pool a été drainé.
essayer:
OriginalL'auteur Pizzaiola Gorgonzola