Need to check for nil before allocating object - ios

As the title says: is it necessary or is it good practice to check if an object is nil before allocating and initializing it, like so?
if (!_menuFetcher) {
_menuFetcher = [[MenuFetcher alloc] init];
_menuFetcher.delegate = self;
}
I presume this is called lazy loading right?

Lazy loading is deferring the creation of an object until you need it. UIViewController does that with its view -- creating a view hierarchy takes a good deal of time and memory, so it isn't done until the view is accessed. You might implement lazy loading using a conditional statement like the one you've shown. Ideally, you'd put that in the accessor for a property and use the property everywhere so you don't have conditionals all over the place.
It's not bad practice to check whether an object exists, but using properties lets you limit the number of places where you need to do so, which simplifies the rest of your code.
It's not necessary to always check whether something exists before allocating -- most of the time you should already know. For example, in your -init method you know that nothing has been allocated yet, and you can create whatever objects your new object will need.

Yes, this basically prevents re-initialising something that was already initialised. You should always do this, unless you are 100% sure that you are not re-initialising. However, this is not called Lazy Loading - that something different.
Lazy loading is used, for example, when loading images in a table view. Instead of loading all of the images that are in the table view, you only load these ones that are visible on screen. This approach is better for loading times, performance and memory.

Usually you do something like this in a getter method.
Say you have a property:
#property (nonatomic, strong) MenuFetcher *menuFetcher;
That you use in a view controller say, then you can implement a getter for the property as so:
- (MenuFetcher *)menuFetcher
{
if (!_menuFetcher) {
_menuFetcher = [[MenuFetcher alloc] init];
_menuFetcher.delegate = self;
}
return _menuFetcher;
}
You're correct that this is a form of lazy initialisation (rather than loading) - the memory is not allocated nor the instance initialised until the point it is required. Also, you don't need to have a centralised initialisation routine, nor do you need to worry about the object being set up yet - if it doesn't exist it gets created - if you blow it away by setting it back to nil, the next time something wants an instance of that type, it gets created again. So it is somewhat elegant and efficient in that regard.
So, in effect, the first time you try to read the property by calling self.menuFetcher, if it hasn't been setup yet, your getter will notice it is nil and create and initialise it for you. Once set, the property is no longer nil, so the getter just returns the object as held.
Use lazy initialisation if that is appropriate for what you are writing. The only thing to really watch out for is getters that do other things beyond the lazy initialisation - getters that have 'side effects' can be a pain if things go wrong. Keep them simple and focused.

It depends.
If you just need to instanciate a new object then there is no need to check for nil.
There is no need to check for nil before allocating an object. Not at all.
However, this is some quite good and widely spread pattern where you check for nil before acutally using the object. If the reference is nil then you create it 'on the fly'. You have to see it in the context of the following code (either here or in the caller). There _menuFetcher will be used in some way. (most probabyl at least.)
Or this is in a method that may be called multiple times like viewWillAppear in a view controller. You may have good reasons not to instanciate and initilize the object earlier and wnat to instanicate it only once. On the next call of that very method you would simply reuse the object that was created earlier.
(I meant to write this in a comment first, not an answer. But it became to long for a comment.)

Lazy loading means 'loading on demand', you perform operation only when it is really needed, it something like:
- (MenuFetcher *)instance{
if (_menuFetcher == nil){
_menuFetcher = [[MenuFetcher alloc] init];
}
return _menuFetcher;
}

Related

Why init.. methods are required in Objective C?

Wherever I've read, it's written to never use an object without calling it's initializer function. And initializer functions always "have to" start with "init".
Is there a reason behind this naming (Does naming a method starting with init do something special)? What happens if I do not call the initializer function i.e. if I just do [MyClass alloc] and start using the object?
Alloc is called to allocate space in memory for the data type you are specifying. Whether it is NSString or NSNumber, calling Alloc will reserve the most efficient space in memory as possible for that data type (small or large).
Init is called to instantiate the class and superclass's important variables. These variables could include the Rect to recalculate a certain size in order to layout subviews, or perhaps instantiate with a delegate of some kind to perform some protocol upon creation. If it all becomes too much for you Objective-C does allow you to instantiate objects like MyClass *myObject = [MyClass new];
It may all seem redundant and a waste of time, but fortunately Swift has cut down tremendous amounts of redundancies like this in the new programming language. Now all you have to do is var myObject = MyClass() and if there are any custom initializers they would likely be writen like so var myObject = MyClass(frame: CGRectZero)
Happy coding!
I recommend reading the Apple Documentation on Object Initialization, and Initialization.
Is there a reason behind this naming (Does naming a method starting with init do something special)?
It is the convention, beginning a method name with init does not do anything special.
There are some minor quirks, such as if a method beginning with init returns type id, the compiler will convert the return type to instancetype, but these are barely worth mentioning.
What happens if I do not call the initializer function i.e. if I just do [MyClass alloc] and start using the object?
If you're using a standard SDK class, you'll likely run into a crash / exception. Initialization is used to set up the initial state of the instance variables, and without doing this can lead to undefined behaviour.
For a small example, if you called [[MyObject alloc] vegetable]; with the following class, you'd get nil returned because _vegetable hasn't been assigned.
#interface MyObject : NSObject
-(NSString*)vegetable;
#end
#implementation MyObject {
NSString *_vegetable;
}
-(instancetype)init {
self = [super init];
if (self) {
_vegetable = #"Cabbage";
}
return self;
}
-(NSString*)vegetable {
return _vegetable;
}
#end
It is the way you create objects in Objective-C. It is a hard requirement of the language. Creating an object in Objective-C is a 2 step process: alloc and init.
Under the covers, the reason you must call init is, wait for it, initialization.
The call to alloc creates a block of memory for your object and zeros it out. Calling init allows the object and it's ancestors to set things up so the object is ready to function. It initializes the object's memory and does other housekeeping that set the object up.
Further, every object's init method needs to call super init, so the initialization goes all the way up the object chain, all the way to NSObject. All the ancestor classes are designed to assume that their init method is called.

What is the use of storing the block in an instance variable

I am aware that blocks are one of the latest feature added in ios. But I am really finding a
tough time learning it .
I have seen people doing the following
typedef void(^CallBackBlk) (NSString *);
#property(copy,nonatomic)CallBackBlk block;
and in .m class
-(void)doSomething:(CallBackBlk )cb{
self.block=cb;
}
I never understood what is the use of assigning it to cb here. Can't I simply do the following
-(void)doSomthing{
block(#"my string");
}
I am really not getting the purpose of storing the block in instance variable. Can any help
me with an example. Any help is greatly appreciated
In your doSomething method, where does block come from?
Answer that, and you'll have your reason.
Ah -- the commentary makes the question clear. Snark served a purpose (snark and too lazy to type out a real answer on my iPhone at 7AM :).
An instance variable is just a slot to put things. Nothing is in that slot to start with.
In your case, you could implement:
-(void)doSomething:(CallBackBlk )cb{
cb();
}
However, typically, a callback is used when you do something asynchronously. For example, you might do:
[myObject doSomething:^{
NSLog(#"did something");
}];
And then:
-(void)doSomething:(CallBackBlk)cb {
dispatch_async(... global concurrent queue ..., ^{
... do some work ...
cb();
});
}
That is, doSomething: will return as soon as the dispatch_async() happens. The callback block is used to callback to let you know that asynchronous operation is done.
Of course, still no need for an instance variable. Take that class that does something a bit further; make it some kind of relatively complex, state transitioning, engine. Say, like your average internet downloader or compute heavy simulation engine. At that point, lumping all your background work into a single method would be overly complex and, thus, shoving the callback block(s) (there may likely be more than one; a progress updater, a completion block and/or an error block, for example) into instance variables allow the class's implementation to be subdivided along lines of functionality more cleanly.
What is the use of storing the block in an instance variable
Perhaps to be able to access it later?
You would do that if you want to invoke the block later, after the method that assigns it has already returned.
Consider for example an object that manages a download. You might want to have a block that gets invoked when the download completes (e.g. to update the UI), but you don't want the download method to have to wait until that happens (because it might take a long time).
maybe and example of use will help..
one use for storing it as a variable i have found is if you have multiple views that all access another view (for me it was a map on the next view) i used blocks that were setup by the previous view (set the default location for the map, initialise markers and so forth) then passed it through to the next view, where it would run it, setting up the map. it was handy having the block use the local variables of the previous view to access certain attributes. it wasnt the only way to do it, but i found it was a nice clean way of going about it.
and here is an example of what gets run in the viewDidLoad of the mapview
if(setupMap){
setupMap(mapView);
}
if(gpsUpdate){
gpsUpdate(mapView);
}
if(addMarker){
addMarker(mapView);
}
now if those blocks were assigned (the if statement check if they are nil), it would run them and do the appropriate setup for the map. not every view needed to do those, so they would only pass to the map view what needed to be done. this keeps the map view very general purpose, and code gets reused a lot. write once use lots!
To use the block, you call your doSomething: method:
CallBackBlk laterBlock = ^(NSString *someString) {
NSLog(#"This code is called by SomeClass at some future time with the string %#", someString);
};
SomeClass *instance = [[SomeClass alloc] init];
[instance doSomething:laterBlock];
As you code the implementation of your class, it will presumably reach some condition or finish an action, and then call the laterBlock:
if (someCondition == YES) {
self.block("Condition is true");
}

iOS 6 - When to instantiate (create an object of the class) and when not to?

I am trying to understand the instantiation process better. I understand that some classes need to be allocated and initialized (I have to create an object of the class) before I can use them, such as NSMutableArray. However, I am running into classes that I do not need to instantiate before I use them, such as NSDate and UIImage.
For example, I have always been instantiating NSMutableArray like this before I can use it:
NSMutableArray *myArray = [[NSMutableArray alloc]init];
With UIImage I can just skip instantiation and just do this:
UIImage *i = [UIImage imageNamed:#"image.png"];
Are there any rules or tell-a-signs for when I can just use a class without instantiating and when I have to instantiate? I'm trying to see if there is a quick way of knowing this.
Thanks!
You are always instantiating an object in either case. It is just that the UIImage class provides some static convenience methods that hide the rather ugly alloc/init process. Even NSMutableArray has [NSMutableArray arrayWithCapacity:numItems] which still does 'alloc', 'init' inside of it but also sets up an initial capacity (for performance reasons). The best way is to peruse the docs, looking for static class methods, or seeing if autocomplete has any methods that begin with the thing you are making, e.g. [UIImage image...] and [NSDate date...]
In general, my own rule of thumb is if the object is only going live within that method and not be used outside the scope of that method, I'll use a creation API for an object thats autoreleased before I instantiate a new object.
But, if you need to access the object anywhere else outside of the scope of the method, you must instantiate it and have the memory retained and stick around.
In your example above, if you're taking "UIImage * i" and dropping it into an image view or doing something with it only within a single method, then "imageNamed" is perfectly appropriate.
If you need to keep "UIImage * i" around for anything outside the scope of the method, use it's designated initializer instead.

Releasing Singletons

I was wondering how you would release a singleton
+ (DSActivityView *)activityViewForView:(UIView *)addToView withLabel:(NSString *)labelText width:(NSUInteger)labelWidth;
{
// Not autoreleased, as it is basically a singleton:
return [[self alloc] initForView:addToView withLabel:labelText width:labelWidth];
}
When analysing this using the analyse tool i get the following error :
Potential leak of object on line 90. which is the line that returns.
I have tried autorelease that solves the error message problem but im not convinced its the right solution since i read that autoreleasing singletons is not good. Would someone be able to assist me in identifying how best to release this object?
Thanks
The reason why the analyzer gives you the warning is, basically, the method name:
+ (DSActivityView *)activityViewForView:(UIView *)addToView withLabel:(NSString *)labelText width:(NSUInteger)labelWidth;
according to Objective-C conventions, all method names starting with "create"/"new"/... return a retained object; your method falls under the category of convenience constructors, which are expected to return autoreleased objects, hence the warning.
On the other hand, you say this is a singleton, but in fact it is not. So, you could possibly end up calling this method more than once and thus have an actual leak. A basic way to make your method safer (and more singleton-like) is:
+ (DSActivityView *)activityViewForView:(UIView *)addToView withLabel:(NSString *)labelText width:(NSUInteger)labelWidth;
{
static DSActivityView* gDSActivityViewSingleton = nil;
if (!gDSActivityViewSingleton)
gDSActivityViewSingleton = [[self alloc] initForView:addToView withLabel:labelText width:labelWidth];
return gDSActivityViewSingleton;
}
This would both make the analyzer relax and give you more safety in front of the possibility of misuse of the method.
Use autorelease. There's no reason not to. Basically ownership of the object belongs to the object, so you're never going to be able to manually release it. As its a singleton it doesn't matter if you don't own it because presumably next time you call it and need it in scope you'll use another convenience method and it will get instantiated again.
If you want to have ownership of the object then you will need to instantiate it as normal and then you will be able to retain and release it.
Also, read sergio's edit about it not being a "proper" singleton. :p
Also, if you can, convert to ARC and you won't have to worry about this!
U are doing it wrong. Consider:
If you calling activityViewForView multiple times, you won't get get the same object over and over again. It only would initialize a new object and give you the pointer to it!!!
To make this thing a singleton, you have to store the created object in a constant variable and make sure, you have a reference to this object all the time your app is running (for instance declare your pointer to this object in appDelegate).
Then every time you call activityViewForView you have to check the constant variable if it is pointing to a valid object. If so, return the valid object, if not, create it and store it in your constant static variable (creation is done only once).
If you do use ARC you're all set. If not, release your object (use dealloc method)

Creating Objects on the fly in Objective-C

I'd like a critique of the following method I use to create objects:
In the interface file:
MyClass * _anObject;
...
#property (retain, nonatomic) MyClass * anObject;
In the implementation file:
#property anObject = _anObject
so far, so simple. Now let's override the default getter:
(MyClass *) anObject {
if(_anObject == nil) {
self.anObject = [[MyClass alloc] init];
[_anObject dowWhateverInitAction];
}
return _anObject;
}
EDIT:
My original question was about creating the object only (instead of the whole life-cycle), but I'm adding the following so that it doesn't through off anyone:
- (void) dealloc {
self.anObject = nil;
}
/EDIT
The main point of the exercise is that setter is used inside the getter. I've used it for all kind of objects (ViewController, myriad other types, etc.) The advantage I get is:
An object is created only when needed. It makes the app pretty fast
(for example, there are 6-7 views in an app, only one gets created in
the beginning).
I don't have to worry about creating an object before it's used... it happens automatically.
I don't have to worry about where the object will be needed the first time... I can just access the object as if it were already there and if it were not, it just gets created fresh.
Questions:
Does it happen to be an established pattern?
Do you see any drawbacks of doing this?
This pattern is quite commonly used as a lazy-loading technique, whereby the object is only created when first requested.
There could be a drawback to this approach if the object being created lazily takes a fair amount of computation to create, and is requested in a time-critical situation (in which case, it doesn't make sense to use this technique). However I would say that this is a reasonable enough thing to do should the object be quick to create.
The only thing wrong with your implementation (assuming you’re not using ARC yet) is that you’ve got a memory leak—using the setter means that your MyClass instance is getting over-retained. You should either release or autorelease _anObject after that initialization, or assign its value directly instead of calling the setter.
Aside from that, this is totally fine, and it’s a good pattern to follow when the MyClass is an object that isn’t necessarily needed right away and can be recreated easily: your response to memory warnings can include a self.anObject = nil to free up the instance’s memory.
It looks like a decent lazy initialization. Philosophically, one can argue that the drawback is that a getter has a side effect. But the side effect is not visible outside and it is kind of an established pattern.
Lazy instantiation is an established pattern, and it is used by Apple in their (terrible) Core Data templates.
The main drawback is that it is overly complex and often unnecessary. I've lost count of the number of times I've seen this where it would make more sense to simply instantiate the objects when the parent object is initialised.
If a simple solution is just as good, go with the simpler solution. Is there are particular reason why you can't instantiate these objects when the parent object is initialised? Perhaps the child objects take up a lot of memory and are only rarely accessed? Does it take a significant amount of time to create the object and you are initialising your parent object in a time-sensitive section of your application? Then feel free to use lazy instantiation. But for the most part, you should prefer the simpler approach.
It's also not thread-safe.
Regarding your advantages:
An object is created only when needed. It makes the app pretty fast (for example, there are 6-7 views in an app, only one gets created in the beginning).
Are you referring to views or view controllers? Your statement doesn't really make sense with views. I don't normally find myself needing to store view controllers in instance variables/properties at all, I instantiate them when I need to switch to them and push them onto the navigation stack, then pop them off when I'm done.
Have you tried your app without using this pattern? Conjecture about performance is often wrong.
I don't have to worry about creating an object before it's used... it happens automatically.
No, now you have to worry about writing a special getter instead. This is more complex and prone to mistakes than simple instantiation. It also makes your application logic and performance more difficult to understand and reason about.
I don't have to worry about where the object will be needed the first time... I can just access the object as if it were already there and if it were not, it just gets created fresh.
You don't have to worry about that when you instantiate it during your parent object's initialisation.
Yes this is an established pattern. I often use lazy instantiation like this as an alternative to cluttering up -init or -viewDidLoad with a bunch of setup code. I would assign the value to the instance variable instead of using the synthesized setter in the event that this object ends up being created as a result of something happening in -init.

Resources