As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 9 years ago.
So it seems lazy instantiation is widely used and everybody know the advantages of lazy instantiation.
Which leads to the question: should we lazy instantiate every object?
Which I seriously doubt.
So the question is, what are the disadvantages of lazy instantiation?
Sample taken from (Apple Sample LocateMe):
- (NSDateFormatter *)dateFormatter {
if (dateFormatter == nil) {
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeStyle:NSDateFormatterLongStyle];
}
return dateFormatter;
}
This will give us the advantage of only initialising this object when it is needed.
By the way, the above sample taken from Apple, it seems like they only lazy instantiate "readonly" objects.
Ok, figured I'll reword my response in the form of an answer (ad you've got too many comments now)...
In the example you've given, it's safe to use the same object instance multiple times as its internal state is unaffected. That is, it's providing a service and won't keep state between calls.
As a general rule, lazy instantiation is only really relevant to Singletons or those instances provided through a factory. For instance, like in your example, instances living for the duration of a "service" or application - such as resource handling. Usually though, you often just want to create a new object instance when you need it.
The advantages/ disadvantages of lazy initialization are:
You need initialize an object only once and a single instance will suffice for all service calls. State won't be held between calls. The benefit here is that the object may be time-consuming to load and so you avoid start up cost or, in a singleton context, you avoid instantiating multiple expensive objects. This also applies to memory footprint - one instance, rather than many.
There is a cost at run-time though if you do lazily ini an object as you've essentially delayed its construction. So, at run-time, when a user is waiting, you go and create an expensive object. Not ideal so you should avoid this - if it's a long-service object again.
In the example you've given, there's also a question of responsibility for memory. The client code is clearly responsible for releasing this instance. If it's a long serving object, where do they do it? Well, you may have to watch the NSApp's delegate for applicationWillTerminate.
If an instance maintains state that would be set between invocations of methods on an instance then this pattern can't work. The state of the instance may be inconsistent (may have been changed) between calls.
Note also that this is an instance method setting the value of an instance var if it's null... This means that, in this case, you will still have one instance per your enclosing class instance (class where this method is defined). In this context, your enclosing instance is responsible for clean up. Really, I think that this is for clarity of code, rather than memory management. Or perhaps the enclosing class is long-lived and it saves re-creating your formatter (perhaps it's more expensive to recreate than reset).
will edit if anything else comes to mind. Hope it helps.
Related
I have done a bunch of coding in swift and prefer to do a lot programmatically and I was wondering what the difference was between these two:
self.view.addSubview(someNewView)
view.addSubview(someNewView)
they both seem to work. Is one better for some reason? Are they actually that different?
If this is a dumb question or already answered it can be removed. Just a thought.
There's no real difference, although you may see the use of self more often from previously Objective-C developers. From the docs:
In practice, you don’t need to write self in your code very often. If
you don’t explicitly write self, Swift assumes that you are referring
to a property or method of the current instance whenever you use a
known property or method name within a method.
...
The main exception to this rule occurs when a parameter name for an instance method has the same name as a property of that instance. In this situation, the parameter name takes precedence, and it becomes necessary to refer to the property in a more qualified way.
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Methods.html
I have been looking at Swift the last couple of days and it looks good, I am confused on a point though even after review of the guide Apple published.
I understand that memory management in Swift uses ARC and therefore quite safe, however in situations where I'd like more fine grained control of object creation and destruction I'm slightly confused.
Take these two simple examples:
In ObjC, when you'd (for example) like a UIViewController you intend to push to stay around for the lifetime of your app and only be created once (say because it's expensive to create), you'd make it a property and then wrap it's Alloc Init like this:
if (!self.myProperty)
{
self.myProperty = [[MyObj alloc] init];
}
This way it only creates once, keeps state and the same object instance can be reused indefinitely, yielding known object references, and good performance not having to recreate each time the viewController goes out of scope.
Another example of this is with NSMutableString, vs Swifts String.
You can set an NSMutableString's string many times and it will keep the same object reference, however this doesn't seem to be the case with a Swift String when changing it.
This may just be 'deprecated thinking in Objective C' but is there a best practice with regard to keeping around expensive objects or to keep state (same object) for certain objects during the lifetime of their usage.
I think what you're looking for is a "Lazy stored property":
The example in the swift docs is:
class DataManager {
#lazy var importer = DataImporter()
var data = String[]()
// the DataManager class would provide data management functionality here
}
and it says about #lazy:
A lazy stored property is a property whose initial value is not calculated until the first time it is used. You indicate a lazy stored property by writing the #lazy attribute before its declaration.
The comment about NSMutableString is a little different, you can continue to use NSMutableString in your swift code, but Apple are encouraging developers to use the Swift built-in types whenever possible :)
see the "String Mutability" section in the swift docs
This question already has answers here:
What should my Objective-C singleton look like? [closed]
(26 answers)
Closed 9 years ago.
I have created a singleton class, And Here is code
static DPGameManager *sharedManager = nil;
+ (DPGameManager *)sharedManager
{
static dispatch_once_t singletonPredicate;
dispatch_once (&_singletonPredicate, ^(){
sharedManager = [[DPGameManager alloc]init];
});
return sharedManager;
}
DPGameManager *m1 = [DPGameManager sharedManager];
DPGameManager *m2 = [DPGameManager alloc]init];
DPGameManager *m3 = [DPGameManager alloc]init];
m1, m2, m3 are three different objects.
But we should not be able to create three different object for a singleton class.
How can we achieve this.?
Or is This fine to create different object for a Singleton class.
First of all: A singleton is a class of which you can create one and only one instance object. This is the usual definition and it is the definition that Apple uses. But, funny thing, in the same documentation the examples contains cases, in which this rule is not fulfilled. (I. e. NSFileManager IIRC.) So in Apple's opinion there is not big difference between shared instances and singletons even there is a difference. (Shared instances are "special instances", singletons are lonesome cowboys.)
So – maybe – it is good enough to adopt this "shared instances are singletons even they are not" antipattern. I wouldn't do that. But probably nobody would even think of +alloc, when he finds a method called +sharedInstance. So – again maybe – it is no big deal.
While it has been very easy to adopt the singleton pattern with manual RC, it became a little bit harder with automatic RC. I think the easiest way is to return sharedInstance in -init… as mentioned in the comments. -init… methods are ownership consuming and ownership transferring. (This is not mentioned in Apple's documentation. You should always read the clang docs for this subjects. They are better by far.) So the old instance delivered by +alloc will be consumed and move away.
The Apple Programming with Objective-C document states that:
You should always access the instance variables directly from within
an initialization method because at the time a property is set, the
rest of the object may not yet be completely initialized. Even if you
don’t provide custom accessor methods or know of any side effects from
within your own class, a future subclass may very well override the
behavior.
But I don't know what side effects will be in a setter method, please give me a example to explain why I have to access the instance variable directly from within an initialization method
The answer is simple - it is code smell. Dot notation like self.foobar = something in Objective-C is just a syntactic sugar for messaging.
Sending messages to self is normally fine. But there are two cases you need to avoid them:
1. When the object is being created, and
2. When the object is being destroyed.
At these two times, the object is in a strange in-between state. It lacks integrity. Calling methods during these times is a code smell because every method should maintain invariants as it operates on the object.
If a setter method is overridden by a subclass, you have no guarantee that your instance variable will contain the correct data. If you want to maintain data integrity within your objects during a crucial phase such as initialization, you should do as Apple recommends.
In addition to #JacobRelkin point, side effects can include Key-Value Observing. Other objects can observe changes even during -init* and -dealloc. I've had a KVO -dealloc bug in the past.
It truly is a best practice to setup and tear down the ivars directly.
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.