Say, I want to create a singleton which has some data inside. The data is dynamically allocated only once, as it expected on singleton.
But I would like to now under when and how this data can be is released. Should I establish special method which will destroy the singleton? To be more specific - when the method 'dealloc' for this singleton will be executed? who is responsible for that?
You can declare a method/function you call explicitly.
The simplest way is to have a static C++ class hold it, then release it in its destructor. If you have multiple singletons, then this approach does not extend very well because the destruction order is implementation defined.
Another alternative (and better design) would be to avoid the singleton approach, and just use it as a regular instance in another class which lives for the duration of your app (an app delegate is a commonly known example).
As to 'when', it depends on its dependencies and how it's used. It's also good to try to minimize external influence in destruction.
In general, a singleton is not different to a normal object. It is freed, if there is no (strong) reference to it anymore. Usually, you control that there is one object only by a static variable. This variable is created at compile time; therefore it can not be freed. But all the 'real' object stuff can.
Related
a design question:
I have a singleton (in objective-C but it doesn't really matter)
The singleton is a class (object) that is actually a data structure that many classes access, and is single (hence - a singleton)
Now I want to add the ability to undo - which is actually saving a snapshot of the state of the object - so I can go back to it.
What I actually need to do is to break the singleton-ness of the object (need one copy of it).
But this will not allow me to share it conveniently between all the classes.
Ideas?
"The singleton is a class (object) that is actually a data structure that many classes access, and is single"
I think it is easier to make your singleton object have a collection of the data structure. Then you just create copies of the data structure instead of copies of singleton.
The singleton pattern came in vogue about 10 years ago when design patterns were first being adopted by developers. In the years since then, the singleton has fallen into disuse because it is notoriously difficult to mock in unit tests. So the simplest answer is to abandon the singleton pattern completely in favor of a more friendly pattern.
You could implement a - (id) copy method in your singleton class.
In this method, allocate a new instance of your class, and set all it's properties to a copy of your shared instance's properties.
According to Cocoa's "Create Rule" a method that returns a newly instantiated object must begin with either new, create, or copy if ownership is transferred to the caller.
Let's say I have a class that implements a factory method called (NSObject *)getCorrectObject.
This method will return a new instance of the correct subclass of the callee (determined by some internal state of the callee). Technically this method does not follow the "Create Rule" and could lead to memory leaks in non-ARC environments.
Would it be possible to instead use (NSObject *__autoreleasing)getCorrectObject to avoid using new or create in this case?
In non-ARC I would return an autoreleased object, but I'm not entirely sure if __autoreleasing works for anything other than In/Out parameters.
According to Cocoa's "Create Rule" a method that returns a newly instantiated object must begin with either new, create, or copy if ownership is transferred to the caller.
This isn't called the Create Rule (and isn't correct). The Create Rule is a Core Foundation rule related to the words Create and Copy. Cocoa has a different rule related to “alloc”, “new”, “copy”, or “mutableCopy”.
Let's say I have a class that implements a factory method called (NSObject *)getCorrectObject.
Then it would be incorrectly named. Starting a method with get indicates that it returns a value by reference. The correct signature would be:
+ (BOOL)getCorrectObject(NSObject**)result;
This method will return a new instance of the correct subclass of the callee (determined by some internal state of the callee). Technically this method does not follow the "Create Rule" and could lead to memory leaks in non-ARC environments.
That is not based on whether it is a new instance. It's based on whether it includes an unbalanced retain.
Methods that begin with “alloc”, “new”, “copy”, or “mutableCopy” should return an object with one unbalanced retain. Other methods should return an object that has an equal number of retain and autorelease attached to it.
If for some reason you have to violate these naming rules (and you really don't want to violate these rules), the correct way to indicate it to ARC is by using NS_RETURNS_RETAINED (see Foundation/NSObjCRuntime.h for all the macros). This only assists ARC in correctly fixing your memory management when dealing with mixed ARC/Retain code in cases where it is impossible to fix your incorrect naming. Pure ARC code doesn't need this; it'll balance out either way. Pure Retain code won't be helped by this. The caller has to do the right thing (and so has to just know that you did it wrong and compensate).
Note that as long as you're using ARC throughout the project (and you really, really should be), most of this won't matter a lot in practice. ARC will balance everything out for you pretty much no matter what you name things, since you're not in charge of adding the retains, releases, and autoreleases anyway.
When I have a TList (so, a list of "reference to procedure"), and I Clear it, do all the captured variables used in the anonymous methods get freed, so no leaking occurs?
Ie. is reference counting in effect upon clearing the TList?
Delegate types are reference counted like interfaces (in fact they are implemented as interfaces). That means if they run out of scope the object behind the scenes (you might have seen that ArcRec$xxxx thing mentioned somewhere - that is the class name the compiler generates) gets destroyed. Captured variables are implemented as fields inside that class so they also run out of scope and are getting freed.
However you might pay attention to some circular referencing which might cause a memory leak with captured variables because of some important fact:
If you have multiple anonymous methods inside a single routine/method they all are implemented by one single class (that ArcRec$xxxx thing). So in this case the anonymous method with the longest lifetime might keep another one alive even if that already is out of scope.
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.