2010-01-15 12 views
1

J'ai une application iPhone qui a quelques méthodes pour recueillir des informations sur le web et qui crée ensuite un objet, qui contient ces informations en tant que propriétés (disons que j'obtiendrai des objets de type x) . Puisque je pourrais avoir besoin de ce genre d'objets à partir de différents points de l'application, j'ai mis la méthode pour créer une instance de l'objet dans un seul fichier d'implémentation et appelé ce fichier "GetDetails.m" (+ h). Dans cette méthode j'ai exclusivement des méthodes de classe *, (parmi celles-ci ma méthode pour créer l'objet x) qui créent l'objet et remplissent ses propriétés avec les informations que la méthode recueille du web.General Objective-C Question de méthode de classe

+ (ObjX *)getObjectX:(NSString *key) withParameters:(NSArray *)parameters; 

Dans cette méthode mon ObjX est rempli d'informations ...

ObjX *objectX = [[ObjX alloc] init]; 
(...) 
objectX.name = gatheredName; // etc 
(...) 
return objectX; 

Donc, ma méthode de classe est invoquée à plusieurs points depuis l'application (BTW à partir d'un thread séparé.):

Je ne peux pas me débarrasser de la sensation que cette approche n'est pas optimale.
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
ObjX *myObject; 
myObject = [GetDetails getObjectX:@"09384f9a" withParameters:nil]; 
[self performSelectorOnMainThread:@selector(doStuffWithNewObject:) withObject:myObject waitUntilDone:NO]; 
[pool release]; 

Je ne peux pas me débarrasser du sentiment que cette approche n'est pas optimale. L'analyseur Xcode m'indique également qu'il pourrait y avoir une fuite potentielle sur le retour objectX.

Peut-être que quelqu'un pourrait me diriger vers la bonne direction et comment je devrais faire la division des fonctionnalités en général.

* Il ne dispose pas d'une méthode init et dealloc, pas Ivars, aucune méthode d'instance ...


Modifier

Bon, évidemment le plus ne voient pas de sortie pour l'objet , donc je suppose que je n'étais pas clair avec ça - l'objet sera publié plus tard après qu'il soit assigné à une propriété d'une vue. Pourtant, je vois que c'est une pratique de retourner un objet autoreleased. Malheureusement, mon application se bloque quand je fais cela. Peut-être que c'est parce que je cours tout ce traitement dans un pool séparé de thread/autorelease? Je vais tester quelques configurations et vous laisser savoir comment ça s'est passé.

+0

Je pense que c'est une sorte d'hybride torsion usine/méthode singleton? – Eimantas

+0

Eh bien, probablement une méthode d'usine, mais si c'est une méthode singleton ou non est tout simplement pas pertinent je suppose ... – ff10

Répondre

1

L'analyseur vous causera du chagrin parce que vous n'avez pas vos objets lorsque vous les renvoyez. La méthode habituelle serait la suivante:

ObjX *objectX = [[ObjX alloc] init]; 
... 
return [objectX autorelease]; 

Maintenant, en ce qui concerne la mise en œuvre, cela ressemble à un endroit où utiliser des catégories. Je ferais quelque chose comme ceci:

GetDetails_ObjX.h

@interface ObjX (GetDetails) 
+ (ObjX *)objXWithIdentifier:(NSString *)ident parameters:(NSArray *)params; 
@end 

GetDetails_ObjX.m

@implementation ObjX (GetDetails) 
+ (ObjX *)objXWithIdentifier:(NSString *)ident parameters:(NSArray *)params 
{ 
    ObjX *objectX = [[ObjX alloc] init]; 
    ... 
    return [objectX autorelease]; 
} 
@end 

GetDetails.h

#import "GetDetails_ObjX.h" 
#import "GetDetails_ObjY.h" 
... 

Cette configuration pourrait être utilisé comme suit:

#import "GetDetails.h" 
... 
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
ObjX *myObject; 
myObject = [ObjX objectXWithIdentifier:@"09384f9a" parameters:nil]; 
[self performSelectorOnMainThread:@selector(doStuffWithNewObject:) 
         withObject:myObject 
        waitUntilDone:NO]; 
[pool release]; 

Quelques notes, ici:

  1. J'ai utilisé la signature de la méthode objXWithIdentifier... parce que je ne suis pas sûr de ce que le @ "09384f9a "chaîne en fait est. Si c'est une adresse, vous utiliserez objXWithAddress.... S'il s'agit d'un numéro de référence, vous utiliserez objXWithReferenceNumber..., etc.

  2. J'ai dû vérifier cela pour être sûr. La méthode performSelectorOnMainThread... conserve son argument, donc il n'y a aucune préoccupation concernant l'objet qui est libéré avant que la méthode ne soit appelée sur le thread principal.

1

Une chose qui colle pour moi est que chaque fois que vous appelez votre méthode de classe que vous faites:

ObjX *objectX = [[ObjX alloc] init]; 

Ici vous créez une nouvelle instance d'un objet. Cependant, votre exemple de code ne montre pas que vous le libérez. Souvenez-vous que alloc donne à l'objet un nombre de ref de un. De plus, en appelant votre méthode getXXX, vous allez à l'encontre des conventions de gestion de la mémoire. Cela impliquerait que vous récupérez une référence à un objet que vous ne possédez pas. Puisque ce n'est pas le cas, vous devriez au moins appeler votre méthode newXXX ou createXXX pour impliquer que cet appelant est responsable de la mémoire allouée. Une meilleure approche consisterait à la libérer automatiquement et à la conserver par l'appelant.

+0

Je vais aller avec la autorelease, vous avez raison, c'est évidemment la meilleure pratique. Merci. J'ai édité mon post original. – ff10

1

De l'Memory Management Programming Guide for Cocoa: You own any object you create. You “create” an object using a method whose name begins with “alloc” or “new” or contains “copy” (for example, alloc, newObject, or mutableCopy). Si votre méthode ne commence pas par l'une de ces préfixes, vous devez renvoyer un objet autoreleased. Ensuite, l'appelant de la méthode peut retenir l'objet s'il a besoin d'être gardé plus longtemps.

+0

Merci, j'ai changé mon message original. – ff10