2009-07-11 28 views
2

Je classe d'objets de données:Pourquoi mon programme plante-t-il lors de l'accès à une propriété avec soi-même? et un accesseur synthétisé?

@interface Item: NSObject { 
    NSString *title; 
    NSString *text; 
} 

@property (copy) NSString *title; 
@property (copy) NSString *text; 

@end 

@implementation Item 

@synthesize text; 

- (void)updateText { 
    [email protected]"new text"; 
} 

- (NSString *)title { 
    return title; 
} 

- (void)setTitle:(NSString *)aString { 
    [title release]; 
    title = [aString copy]; 
} 

@end 

je peux définir la propriété title très bien lors de l'utilisation des méthodes non synthétisés, mais quand je mets une propriété avec accesseurs synthétisés je reçois une erreur dans la méthode updateText sur la ligne qui lit:

[email protected]"new text"; 

L'erreur est:

*** NSInvocation: warning: object 0x462d2c0 of class '_NSZombie_CFString' does not implement methodSignatureForSelector: -- trouble ahead 
*** NSInvocation: warning: object 0x462d2c0 of class '_NSZombie_CFString' does not implement doesNotRecognizeSelector: -- abort 

Pourquoi identiques non synthétisé un Les ccesseurs fonctionnent et ceux synthétisés ne fonctionnent pas?

L'objet est créé dans le thread principal et Error s'affiche lorsqu'il est accédé à partir du thread NSOperation.

Répondre

0

Le code que vous avez affiché fonctionne très bien pour moi. Y a-t-il quelque chose de différent entre ce code et le code que vous utilisez? Les messages d'erreur que vous voyez font référence aux "zombies", qui sont des pointeurs vers des objets qui ont déjà été libérés. Rien dans ce code ne montre de risque d'un tel comportement, ce qui m'amène à penser que l'erreur réelle est ailleurs.

Une solution possible consisterait à utiliser le débogueur de Xcode pour voir les adresses de vos objets NSString, et utiliser cette information pour déterminer laquelle aboutira finalement à l'avertissement NSInvocation.

+0

L'objet est créé dans le thread principal et Error s'affiche lorsqu'il est accédé à partir du thread NSOperation. – Rod

3

Le compositeur doit être codé de cette façon:

[title autorelease] 
title = [aString copy]; 

Sinon, un autre thread peut obtenir un objet de titre sorti sous ses pieds.

Ou choisir un autre style accesseur constante de la Memory Management Programming Guide for Cocoa

+2

Il n'est pas nécessaire de gaspiller une autorelease pour cela. Le code standard pour un setter défend simplement contre l'égalité de pointeur du nouveau et ancien titre. if (title! = aString) {[libération du titre]; title = [Copie aString]; } –

+0

Attention: ce sont des chaînes et nous les copions pour une raison. title! = aString peut être vraiment méchant avec des chaînes mutables – IlDan

+1

Je préfère l'approche autorelease. Moins de code est meilleur, et 99,9% du temps la différence de performance n'est pas perceptible. –

0

Dans ce code [self setTitle:[self title]] libérerait et dealloc title avant de le copier. Vous devez vérifier si title == aString dans le setter.