2009-08-01 5 views
2

J'ai implémenté un peu de code à partir de l'un des nombreux exemples de code Apple, mais j'ai quelques problèmes, car l'attribut retain de l'une des propriétés ne semble pas fonctionner. Voici la déclaration de propriété:L'attribut de propriété "retain" ne semble pas fonctionner?

@property (nonatomic, retain) EditingViewController *editingViewController; 

Et voici le code:

- (EditingViewController *)editingViewController { 
    // Instantiate the editing view controller if necessary. 
    if (editingViewController == nil) { 
     EditingViewController *aController = [[EditingViewController alloc] init]; 
     editingViewController = aController; 
     [aController release]; 
    } 
    return editingViewController; 
} 

Je comprends que (retenir) est censé faire le compte conserver augmenter de 1 en mission; cependant, le code échoue sauf si envoie moi-même [aController conserve], ou n'envoie pas [version du contrôleur]. Qu'est-ce que j'oublie ici?

Répondre

4

Lorsque vous référencez editingViewController, cela équivaut à self->editingViewController, c'est-à-dire un accès à un ivar. Si vous voulez utiliser un getter ou un setter, vous devez utiliser self.editingViewController ou, de manière équivalente, [self setEditingViewController:aController].

Voilà pourquoi je préfère utiliser un Ivar avec un autre nom à la propriété, par exemple:

EditingViewController* i_editingViewController; 

@property (nonatomic, retain) EditingViewController *editingViewController; 

@synthesize editingViewController = i_editingViewController; 

Ensuite, vous pouvez écrire votre getter paresseux:

- (EditingViewController *)editingViewController { 
    // Instantiate the editing view controller if necessary. 
    if (i_editingViewController == nil) { 
     i_editingViewController = [[EditingViewController alloc] init]; 
    } 
    return i_editingViewController; 
} 

ou

- (EditingViewController *)editingViewController { 
    // Instantiate the editing view controller if necessary. 
    if (i_editingViewController == nil) { 
     EditingViewController *aController = [[EditingViewController alloc] init]; 
     self.editingViewController = aController; 
     [aController release]; 
    } 
    return i_editingViewController; 
} 

J'utiliserais probablement l'ancienne méthode (sans invoquer le setter) car la valeur de editingViewController (comme vu par n'importe quel observateur) n'a pas vraiment changé, mais l'une ou l'autre manière devrait fonctionner correctement et le nom différent (pour l'ivar et la propriété) aide à éviter la confusion ou l'abus accidentel. C'est aussi un léger encouragement à utiliser la propriété (puisqu'elle évite le préfixe un peu moche).

Notez qu'Apple réserve le préfixe _ et que les setters et getters ne doivent pas être utilisés dans les routines init/dealloc.

+0

L'exemple de code m'a vraiment aidé à voir l'erreur de mes manières. Lorsque je résolvais ce problème, j'essayais d'utiliser self.editingViewController sur les trois instances, ce qui bien sûr appelait de manière récursive tableView: editingViewController pour deux d'entre elles. Duh. – JoBu1324

0

Vous devez écrire self.editingViewController afin d'utiliser la propriété. Juste "editingViewController" est un accès direct à la variable membre de classe, tandis que self.editingViewController est équivalent à [self setEditingViewController: ...] et fera le travail de conservation/libération approprié.

Questions connexes