Reputation: 6184
If I have a property, say an NSArray, that's going to be initialized only once for each instance of my class, is there anything wrong with this:
(in the interface)
@property(strong, nonatomic)NSArray *bubbleArr;
(in the implementation)
-(NSArray*)bubbleArr
{
if(!bubbleArr)
{
NSMutableArray *tempBubbArr = [[NSMutableArray alloc] init];
// get filepath for first speech bubble image for page
NSString *speechBubbleImgPath = [[NSBundle mainBundle] pathForResource:
[NSString stringWithFormat:@"speech_%i_0", pageIndex]
ofType:@"png"];
for(int i = 1; speechBubbleImgPath; i++)
{
UIImage *speechBubbleImg = [[UIImage alloc] initWithContentsOfFile:speechBubbleImgPath];
UIImageView *speechBubbleImgView = [[UIImageView alloc] initWithImage:speechBubbleImg];
[tempBubbArr addObject:speechBubbleImgView];
speechBubbleImg = nil;
speechBubbleImgView = nil;
speechBubbleImgPath = nil;
speechBubbleImgPath = [[NSBundle mainBundle] pathForResource:
[NSString stringWithFormat:@"speech_%i_%i", pageIndex, i]
ofType:@"png"];
}
bubbleArr = [[NSArray alloc] initWithArray:tempBubbArr];
tempBubbArr = nil;
}
return bubbleArr;
}
I've never used custom accessor methods, but this seems like a clean way to set it up, so I don't have to set up each property in my viewDidLoad
or elsewhere, and don't have to worry about it being nil
. I don't recall ever actually come across code that does this. Is this the recommended way to do it? Also, I'll always want to use self.bubbleArr
to make sure this method is called, right?
Upvotes: 1
Views: 188
Reputation: 5820
This is a totally valid way of setting up your property. Apple does this sort of thing very often in their sample code as well as in their project templates. Look, for example, at the core data stack setup in a newly created core data iOS project. As @WendiKidd noted, you have to access your variable through the accessors all the time to make sure this works nicely (which is probably what you should be doing anyway).
In particular, this is a good way of implementing a property of a class that can really only return one thing (which, from your comment, it sounds like is what you're trying to do). If that's your goal, here are some guidelines to follow:
readonly
@dynamic
in the implementation and overwrite the getterDeclaring the variable as dynamic in the 4th point will signal to anyone that looks at your code that you've likely written a custom accessor for that property.
Upvotes: 2
Reputation: 4373
The technique of waiting until you need the contents of a variable to initialize it is called 'lazy loading', and is a valid technique. I'm not sure about doing it inside the getter, though.
I think the problem is described exactly by the last line of your post--yes, you would always have to make sure you called the getter method when you wanted to reference the object, even inside the class itself. It's easy to make mistakes and not do that properly, and it's an especially bad idea if your code could be passed on to another developer in the future. They are absolutely not going to expect that you've set things up this way, and could end up with problems when they expect to be able to access the variable as normal. It is common and accepted practice to initialize member variables inside viewDidLoad.
So yes--this is technically possible, though not a very sound setup, design-wise. I would recommend strongly against it. But if you simply want to know if it will function, the answer is yes.
Upvotes: 1
Reputation: 5998
It seems like a clean solution, it feels a bit like lazy loading. But I am not sure I would do it like this.
Upvotes: 0
Reputation: 12832
Yes, if you don't use self.bubbleArray OR [self bubbleArray] you will not be invoking that method.
Other than that, totally a fine way of managing a property's instantiation.
Upvotes: 0