39 votes

NSArray @property soutenu par un NSMutableArray

J'ai défini une classe où je voudrais une propriété publique à apparaître comme si elle est soutenue par un NSArray. C'est assez simple, mais dans mon cas, le soutien réel de ivar est un NSMutableArray:

@interface Foo
{
    NSMutableArray* array;
}
@property (nonatomic, retain) NSArray* array;

@end

Dans mon fichier de mise en oeuvre (*.m) I @synthesize la propriété mais j'ai immédiatement couru dans les avertissements parce que l'utilisation d' self.words est la même chose que d'essayer de modifier un NSArray.

Quelle est la bonne façon de le faire?

Merci!

20voto

Mark Adams Points 17189

Je déclarerais un readonly NSArray dans votre en-tête et remplacerais le getter de ce tableau pour renvoyer une copie d'un NSMutableArray privé déclaré dans votre implémentation. Considérer ce qui suit.

Foo.h

 @interface Foo

@property (nonatomic, retain, readonly) NSArray *array;

@end
 

Foo.m

 @interface Foo ()

@property (nonatomic, retain) NSMutableArray *mutableArray

@end

#pragma mark -

@implementation Foo

@synthesize mutableArray;

- (NSArray *)array
{
    return [[self.mutableArray copy] autorelease];
}

@end
 

14voto

sam Points 1191

J'avais la même question et j'ai trouvé la réponse suivante ici:

http://newwavedigitalmedia.com/blog/?p=305

Fondamentalement, placez la propriété NSArray dans une catégorie de votre fichier d’en-tête et la propriété NSMutableArray dans l’ extension de classe de votre fichier d’implémentation. Ainsi...

Foo.h:

 @interface Foo
@end

@interface Foo (Collections)
@property (nonatomic, readonly, strong) NSArray *someArray;
@end
 

Foo.m

 @interface Foo ()
@property (nonatomic, readwrite, strong) NSMutableArray *someArray;
@end
 

5voto

Tom Andersen Points 3523

Simple:

1) Ne pas utiliser une propriété quand il n'est pas un.

2) le Code se simplifie en:

- (NSArray *)currentArray {
    return [NSArray arraywithArray:mutableArray]; // need the arrayWithArray -    otherwise the caller could be in for surprise when the supposedly unchanging array changes while he is using it. 
}

- (void)setArray:(NSArray *)array {
    [mutableArray setArray:array];
}

Lorsque l'objet est alloced créer le tableau, quand il meurt, dealloc le tableau.

Lorsque de grands effets se produisent à la simple utilisation d'un '.' opérateur, il est facile de négliger extrêmement inefficaces code. Les accesseurs sont ce qu'ils sont. Si quelqu'un appelle aFoo.tableau - le contrat est d'obtenir l'accès à des foo membres du groupe - mais vraiment, c'est juste une copie au moment de l'appel. La différence est assez réel qu'il a provoqué des bugs dans les autres implantations posté ici.

4voto

Andy Points 1448

Ces jours, vous pouvez effectuer les opérations suivantes:

Foo.m:

@implementation Foo {
    NSMutableArray* _array;
}

@end

Foo.h:

@interface Foo

@property (readonly, strong) NSArray* array;

@end

Vous pouvez toujours l'adresse mutable _array par ivar de l'intérieur de la mise en œuvre et à l'extérieur il sera accessible via immuable de la propriété. Malheureusement, cela ne garantit pas que les autres ne peuvent pas le jeter aux NSMutableArray et de les modifier. Pour une meilleure protection contre les idiots, vous devez définir la méthode d'accesseur et le retour immuable copie, cependant, il pourrait être très cher dans certains cas.

Je fait d'accord avec un des commentaires ci-dessus que c'est mieux d'utiliser de simples méthodes d'accès si vous avez besoin de revenir à des données en lecture seule, c'est certainement la moins ambiguë.

2voto

Regexident Points 17722

C'est parce que votre propriété doit correspondre à la réelle ivar type de classe.

Une solution possible/solution de contournement:

//Foo.h:
@interface Foo
{
    NSMutableArray* mutableArray;
}
@property (readwrite, nonatomic, retain) NSArray* array;
//or manual accessor declarations, in case you're picky about wrapper-properties.
@end

//Foo.m:
@interface Foo ()
@property (readwrite, nonatomic, retain) NSMutableArray* mutableArray;
@end

@implementation

@synthesize mutableArray;
@dynamic array;

- (NSArray *)array {
    return [NSArray arrayWithArray:self.mutableArray];
}

- (void)setArray:(NSArray *)array {
    self.mutableArray = [NSMutableArray arrayWithArray:array];
}

@end

Vous êtes en train d'ajouter un privé mutableArray propriété dans une classe de vulgarisation et de sensibilisation du public array il suffit d'envoyer à votre mutable un.

Avec les plus récentes extensions de langage de ObjC, j'ai tendance à supprimer l'

{
    NSMutableArray* mutableArray;
}

ivar bloc entièrement, si possible.

Et de définir les ivar à travers le synthesization, comme tel:

@synthesize mutableArray = _mutableArray;

ce qui va générer un NSMutableArray *_mutableArray; exemple pour vous.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X