Question

I'm fighting with something and I don't find any satisfying solution.

I have a class with a "myMutableArray" member.

I would like the class to manage itself adding and removing items from the array, so I don't want any other class being able to access the member and call NSMutableArray methods on it.

In an ideal situation, I would like to have a private getter (to be able to call self.myMutableArray) and a public setter for this member.

Do you know how I may achieve this ?

In other words :

I would like other classes

be able to call

- [oneInstance setMyMutableArray:thisArray]; // set
- oneInstance.myMutableArray = thisArray; // set using setter

- thisArray = oneInstance.myMutableArray; // get
- [oneInstance addItem:anItem]; // add

not being able to call :

- [oneInstance.myMutableArray add:etc...] // add

I would like my class

be able to call

- self.myMytableArray = [NSMutableArray array]; // set
- thisArray = self.myMytableArray ; // get

Thank you.

Was it helpful?

Solution

Foo.h

@interface Foo : NSObject
@property(readonly, retain) NSArray * myReadonlyArray;
- (void) addItem: (Item *) anItem;
- (BOOL) publiclyDoSomething;
@end

Foo.m

@interface Foo()
@property(readwrite, retain) NSMutableArray * myMutableArray;
- (void) doSomethingInPrivate;
@end

@implementation Foo
@synthesize myMutableArray = myMutableArray_;

- (void) addItem: (Item *) anItem
{
    // assuming myMutableArray_ was already iniitialized
    [self.myMutableArray addObject: anItem];
}

- (NSArray *)myReadonlyArray
{
     return self.myMutableArray;
}

... rest of methods (including the public/private) implementations ...
@end

Some details:

  • Objective-C has "instance variables", not "member variables".

  • The above defines a public getter and private setter that is synthesized automatically. For clarity's sake, I also added a public method and a private method.

  • "Public" and "private" in Objective-C are defined entirely by visibility to the compiler. The setter for myMutableArray and the method doSomethingInPrivate are only private because their declarations in an @interface cannot be imported.

  • self.myMutableArray and [self myMutableArray] do the same thing; the . syntax is merely short hand for an equivalent method call (with a few edge case details beyond this question)

  • @property in the @interface is purely short hand for method declarations (with a bit of extra metadata).

  • @interface Foo() is a class extension and not a category. It exists for exactly the purpose demonstrated above; to extend the @interface of a class with additional declarative information whose scope should be limited. It can appear in a header file that, say, you only import in your library's implementation to create library-private functionality.

  • @dynamic is used when you neither @synthesize an @property nor provide a conventional method implementation. It is not needed otherwise!

I'm probably forgetting something.

OTHER TIPS

Is there any reason you need the public setter? It sounds like the class itself owns the array. You'd probably be better off not providing any public property access to the field, and making a public method which copies the values into your private field.

// public interface, in the .h file
@interface MyClass : // superclass, protocols, etc.
- (void) setSomething:(NSArray *)values;
@end

// private interface, not in the .h
@interface MyClass ()
@property (/* attributes */) NSMutableArray *myMutableArray;
@end

@implementation MyClass
@synthesize myMutableArray = myMutableArray_;

- (void) setSomething:(NSArray *)values
{
    [self.myMutableArray setArray:values];
}

@end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top