I am declaring a property in my class in header file;
@property (readonly) NSArray *pages
That's how I want it to be exposed publicly. Internally though, I am going to allocating it as NSMutableArray so I can add/remove stuff from it. But to do that, I will have to type cast every time. Is there a better way to do this? Thanks
Your approach is really bad. If you insist on exposing a mutable array with dynamic content, then modify your getter to return an immutable copy, otherwise you are going to get weird side effects and exceptions for mutations during fast enumeration.
There isn't a solution for this. You have to cast every time, or use different properties. Here is a sample for the second approach:
@interface MyClass : NSObject
@property (nonatomic, strong, readonly) NSArray *pages;
-(void)addObject:(id)obj;
@end
@interface MyClass()
@property (nonatomic, strong, readwrite) NSMutableArray *mPages;
@end
@implementation MyClass
-(id) init {
self = [super init]
if (self){
_mPages = [NSMutableArray array];
}
return self;
}
-(NSArray*)pages {
return [NSArray arrayWithArray:self.mPages];
}
-(void)addObject:(id)obj {
[self.mPages addObject:obj];
}
@end
int main(int argc, char *argv[]) {
@autoreleasepool {
MyClass *m = [MyClass new];
[m addObject:@"x"]; // the collection is mutable
NSLog(@"%@",[m pages]); // but only accessible as an immutable copy
}
}
This will be expensive if you access the collection frequently, and may be out of sync with the internal mutable collection (which may be mutated while you iterate on the copy).
Copying can be avoided returning the internal mutable instance (NSMutableArray) disguised as an immutable class (NSArray), but that incurs the following risks:
Note that the following idiom doesn't solve the problem:
@interface MyClass : NSObject
@property (nonatomic, strong, readonly) NSArray *pages;
@end
@interface MyClass()
@property (nonatomic, strong, readwrite) NSMutableArray *pages;
@end
This lets you set the variable, but not use it as a different class than the one declared in the interface. In other words, it forces you to cast on every use:
[(NSMutableArray*)pages addObject:@"x"];
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With