2010-11-19 11 views
0

Je suis curieux de savoir si le code que j'utilise ici est un bon moyen de le faire. Fondamentalement, je suis en train de créer un objet modèle simple (au sens MVC) en l'instanciant depuis mon ViewController. L'idée étant que la première fois que j'appelle [[self dataModel] doSomething]; il crée un nouvel objet (ou réutilise un existant). J'ai été spécifiquement concerné par la mise en place de la propriété et la publication correcte de l'alloc local, tous les commentaires seraient très appréciés.Modèle de répartition/retenue (mvc)?

// INTERFACE 
DataModel *dataModel; 
@property(nonatomic, retain) DataModel *dataModel; 

// IMPLEMENTATION 
@synthesize dataModel; 

// Lazy Instanciation ... 
- (DataModel *)model { 
    if(!dataModel) { 
     DataModel *tempDataModel = [[DataModel alloc] init]; 
     [self setDataModel:tempDataModel; 
     [tempDataModel release]; 
    } 
    return dataModel; 
} 

// Clean up 
- (void)dealloc { 
[dataModel release]; 
[super dealloc]; 
} 

OU: (bien que je ne aime pas vraiment cela comme il semble déroutant pour moi)

// Lazy Instanciation ... 
- (DataModel *)model { 
    if(!dataModel) { 
     [self setDataModel:[[DataModel alloc] init]]; 
     [dataModel release]; 
    } 
    return dataModel; 
} 

gary.

Répondre

1

Le premier est meilleur, et assez standard et approprié. La deuxième forme est la mauvaise forme générale. Parce que c'est complètement flou l'objet que vous est le même que vous release. Il est toujours préférable de penser comme ceci:

instiate object 
do something with object 
release object 

Dans ce cas, « faire quelque chose avec l'objet » arrive à assigner à une variable d'instance différente. Mais ce n'est pas grave ce que vous faites là-bas, le modèle est vrai. C'est entièrement à la méthode setDataModel: qu'est-ce qui arrive à l'objet par la suite.

Personnellement, je préfère le autorelease pour la plupart de ces cas. Tout simplement parce que vous devez y penser beaucoup moins.

DataModel *tempDataModel = [[[DataModel alloc] init] autorelease]; 
[self setDataModel:tempDataModel]; 

Ainsi, le modèle plus facile à retenir est la suivante:

instantiate and autorelease object 
do something with object 

Mais ceci est une question de goût, et beaucoup préfèrent l'release explicite.

+0

Salut, si possible, j'ai essayé (en règle générale) pour éviter d'utiliser autorelease. Mais je peux voir votre point de vue, il rend la méthode beaucoup plus simple, plus il n'y en aura jamais qu'un seul, donc les frais généraux sont minimes de toute façon. Très appréciée. – fuzzygoat

+1

'release' est" meilleur "que' autorelease' car il est plus probable qu'il libère la mémoire plus tôt. Mais dans mon expérience, 'autorelease' conduit à moins de bugs _far_ et empêche beaucoup de super difficile de déboguer la douleur associée à des problèmes de gestion de la mémoire.C'est parce que vous pouvez équilibrer l'init et la version droite au même endroit et il est très facile de dire si elle n'est pas équilibrée. Et tant que vos objets ne sont pas un énorme paquet de données, 'autorelease' ne causera pas beaucoup de frais généraux. –

1

La première façon est plus claire, bien que l'effet soit le même. Notez, cependant, que si l'idée de faire dataModel une propriété et d'utiliser le mécanisme retain de l'accesseur est de conserver tout cela en un seul endroit, l'utilisation directe de l'ivar dataModel rompt cette encapsulation. En fait, il semble y avoir un peu de confusion entre cette méthode model et la propriété dataModel. Il serait préférable de restructurer les choses pour que tout soit dans l'accesseur dataModel lui-même, en évitant cette redirection peu maladroite:

- (DataModel*) dataModel 
{ 
    if (! dataModel) 
    { 
     // direct ivar access is legit inside the accessor itself 
     // (at least, I would say so -- no doubt others will disagree!) 
     dataModel = [[DataModel alloc] init]; 
    } 

    return dataModel; 
} 
1

Vous pourriez envisager redéfinissant la getter synthétisé dataModel. Sinon, il pourrait être un peu déroutant à la fois avec le getter dataModel et les messages du modèle.

Je pense que vous pouvez remplacer votre getter synthétisé comme ceci:

- (DataModel *)dataModel { 
    if(!dataModel) { 
     dataModel = [[DataModel alloc] init]; 
    } 
    return dataModel; 
}