I have a pool of objects I keep inside an NSMutableArray so if any other objects want to reference them instead of creating new objects I will simply give it a reference to an object I have already created.
In the past I would monitor retain/release calls on these objects, and when they reached a retain count of 1 (my array only) I would remove them from the array. However I am struggling to do this with ARC because it doesn't let me monitor retain/release, how would I go about doing this?
Creating a way to manage objects based on release/retains calls, it's dangerous. If Apple happens to change the way it works, you are screwed. And apparently, that's what happened, when you start using ARC. There are two things:
1) You want to keep the objects inside the NSMutableArray independently if they are being use by other objects or not. In that case, just create a __weak reference to that objects, and in that way your object, that is inside the NSMutableArray, is kept alive.
2) Once there are not references to the object, just remove it from the NSMutableArray. Add to the NSMutableArray a __weak object. Once the strong one is release, the one inside the array will be as well, although I don't really like this approach as I find it dangerous. If you go for this option, use this to store the objects:
NSValue *weakObject = [NSValue valueWithNonretainedObject:anObject];
[array addObject:weakObject];
In the end, you can simply remove ARC from that specific file, and you can keep the monitoring.
I wouldn't bother with such a complex system. Just work with strong and weak properties and don't try to second guess performance. You are trying to build a memory management system yourself which makes little sense with ARC around. Creating and deleting objects is generally a tiny percentage of performance of any objective-c app; after years of using Instruments to monitor performance I don't worry about this part any more.
First, you should write simple code, intended for humans.
Do not worry about such performance issues until you have proven (via instruments or some other measure) that this is a critical bottleneck.
That said, creating certain objects can be really expensive, so keeping a cache for certain objects is not in and of itself a bad idea. However, you should never rely on reference counts, even in non-ARC code. Apple docs are very clear about this.
The alternative, as Jacky pointed out is a weak reference. Unfortunately, you can not put a weak reference into standard collections (though, ironically, you can put them in C++ collections and they will be managed correctly).
However, you can create a simple wrapper class to hold a weak reference.
#interface WeakWrapper : NSObject
#property (readonly) id object;
- (id)initWithObject:(id)object;
#end
#implementation WeakWrapper {
__weak id _object;
}
- (id)object {
return _object;
}
- (id)initWithObject:(id)object {
if (self = [super init]) {
_object = object;
}
return self;
}
#end
You can then place these objects inside collections, and then...
WeakWrapper *wrapper = // get the object from the collection
id object = wrapper.object;
if (nil == object) {
// You know the object that was being referenced no longer exists
// so this wrapper can be removed from the collection and destroyed.
}
Related
I am little confused about using Strong or Weak in my particular case.
I have one class ParentClass which has 3 object ContainerClass1, ContainerClass2 and ContainerClass3.
Each ContainerClass has its own strong properties with Mutable objects like NSMutableArray
Now in my case, I have to show only one ContainerClass at a time, so if ContainerClass1 is shown then ContainerClass2 and ContainerClass3 is not required.
So I thought when I show ContainerClass1, will set ContainerClass2 and ContainerClass3 objects to nil. Here I am confused whether just setting the other ContainerClass(not shown) to nil will release its memory? because they have strong properties to other objects.
Or should I need to set all other ContainerClass's strong properties to nil first and then set ContainerClass to nil?
Thanks in advance.
#zoeb, may this link will help you to keep away from basic memory problems.
how-to-overcome-memory-problems-in-iphone-applications-with-automatic-reference-counting
Edited:
As we know that Apple introduced ARC in IOS 5.0, ARC is compiler level feature that simplifies process of lifetime of objective-c objects. Before ARC introduced, We managed memory manually means “Manual Reference Counting(MRC)” . With MRC, Developer need to remember when to release or retain object. Means that Developer need to manage life cycle of objective-c objects.
According to Developer perspective, We are mostly interested to adding new features in our application rather then focusing on memory issues. But the things is sure that memory management perform crucial role in application success. To Provide help to Developer, Apple was figure out the way of automatically manage memory.
ARC is smartly manage memory but this is not 100 percent. We need to focus on some points while development to remove our application from lack of memory problem. Here i will try to provide solution of manage memory in ARC base application. that is not 100 percent as well. but its will try to help compiler to estimate life cycle of objective object.
Here are the some steps that you need to implement in your every controllers.
Step 1. Declare weak property to every UI Controls that used in application.
Example : #property (nonatomic, weak) IBOutlet UIButton* btnPost;
#property (nonatomic, weak) IBOutlet UITableView* tblMessages;
etc.
Step 2. As per our developer most confusing question is that whether compiler allow to declare “dealloc” method in ARC base application. the answer is yes but don’t allowed to declare “[super dealloc]” inside it. so override “dealloc” method in every controllers.
-(void)dealloc{
}
Step 3. Remove heavy loaded object from superview in “dealloc” method rather then setting just “nil” reference like MKMapview, ScrollView etc.
-(void)dealloc{
dictAddress = nil;
arrayList = nil;
[map removeFromSuperview];
[scrollView removeFromSuperview];
}
Step 4. Avoid dead lock mechanism. (Example : Class A and Class B is there. Class B is declared Delegate with property type “Strong”. so that Class A and Class B dependent on each other on one is going to release. so in that case “dealloc” method is not called of either classes. so that class keep in memory. to removed such cases we need to keep “Assign” reference to Delegate object.) this is just for example. We need to consider other things as well like “Keep weak reference for block so it will release objects once its execution completed”.
these are the basic steps that avoiding memory problems. Still if you face memory problems then you need to take help of Analyzer to find leak and memory usage.
Below link will help you to analyze memory.
Mamory analyzer
The confusion between strong and weak will be clear with the below link.
Differences between strong and weak in Objective-C
I'm writing an iOS app where there is a common object that all views within the app need to access.
I have been creating, and initialising the object within the viewDidLoad event (of the first view controller), and then passing a reference to this object to all other views that need it. This does not seem like the correct way to do things, feels like I'm somehow breaking the MVC pattern since I'm relying that this particular view is always the first to load in order to setup objects that the whole application needs.
I have now modified my app to do the basic object creation and initialisation in the appDelegate "didFinishLaunching...". This is now working and I can access this common object from all of my other views without having to pass around a reference from one view to the other.
Before I go and continue too far, I was hoping to get peoples input on whether this is the correct way to do things, or whether I should be doing anything else? Sorry if this seems like a trivial question, I'm just learning and want to learn how to do things properly.
Thanks in advance :-)
Without repeating what has already been answered, I'd suggest you make your own Singleton object to hold your 'globals', so you don't clutter your AppDelegate with it.
#interface MyGlobalDataController : NSObject
#property (nonatomic, strong) MyData *myData;
+(MyGlobalDataController *)sharedInstance;
#end
#implementation MyGlobalDataController
static MyGlobalDataController *MyGlobalDataControllerSharedInstance = nil;
- (id)init {
self = [super init];
if (self) {
// do whatever needs doing
}
return self;
}
+(MyGlobalDataController *)sharedInstance {
#synchronized(self) {
if (MyGlobalDataControllerSharedInstance == nil) {
MyGlobalDataControllerSharedInstance = [[MyGlobalDataController alloc] init];
}
}
return MyGlobalDataControllerSharedInstance;
}
#end
The first time you access your sharedInstance, the init will be called, so you don't have to worry about timing there.
Putting your global object initialisation in didFinishLaunching is a better idea than having it in didLoad.
Some people will disagree with me here and say you shouldn't have globals full stop, but personally I think having some sort of global state is acceptable. I love a good object-orientated app but there is a balance to be struck between solid OOP and the flexibility provided by having a few globals.
I think ultimately do whatever is right for you, the major disadvantage of having a global state is that it becomes difficult to maintain and has the potential to introduce a lot of bugs / unexpected behaviour especially in a large app, whereas if you stick to the MVC pattern then each view in your app simply does what it is meant to without unnecessarily affecting other parts of the app.
Nowadays, I tend to stick to MVC / OOP principles for the most part, but have an [AppDelegate]sharedAppDelegate] singleton I can use to access variables at certain points. I have very, very few variables in here but they do come in handy i.e. now my app has a shared 'loading HUD' which is managed by this class, and my sharedAppDelegate also contains a lot of static methods for initiating HTTP, parsing JSON etc which saves a lot of time.
One alternative to having global information in your appDelegate is using NSUserDefaults to store key-value information
Hope that helps anyway, like I said some people will disagree with me but ultimately it boils down to personal preferences, and where the balance for you in terms of rigidity to the MVC model versus flexibility is
I'm currently developing a game for iOS and we have a memory leak. Our project is ARC set up. I was wondering on how to ensure memory deallocation. One of the steps I was thinking of taking was convert code of the form:
-(void)methodMethod{
Object* o = [[Object alloc] init];
// Some logic
}
into:
-(void)methodMethod{
Object* o = [[Object alloc] init];
// Some logic
o = nil; // Explicit nil assignment
}
Is there a difference between the two? What other measures should I take to ensure a dealloc in an ARC setup?
We're using the Sparrow Framework.
Both methods do the same thing. Local objects are set to nil by ARC when they leave scope, so putting in a manual nil does nothing.
If you want to find a leak - you are far better off actually running it through Instruments with the Leaks tool and finding out what is being leaked, which will give you a better idea of what is going on. It's quite handy for finding retain-cycles.
As pointed out by Abizem, both methods lead to the same results, and require careful passes through Instruments. The results are not always easy to interpret.
In ARC, you should never see a leak - in the usual obj-C meaning -. Sometimes, iOS instruments can report a leak, but most if not all, this comes from the runtime, and I tend to regard them as beyond my control. What you can see however, is uncontrolled memory increase, which is typical of memory retention. Keeping strong pointers on objects is the obvious reason, which in my case has always been the consequence of : retain cycles in code blocks, and incorrect data structure cleanup, i.e. objects are created, then filled into arrays, dictionary, page control etc... but the later were not emptied properly during the app lifecycle.
Also image processing functions still use standard malloc/free directives embedded into internals UIGraphics lib, so in that case you explicitly need to free the memory (CGImageRelease, etc...). ARC will not help here.
hope this helps narrow down the problem, which as Abizem pointed out, should start with Instruments.
the following is unnecessary but (at least for me) the discussion in the comments was helpful and that's why I leave it
wrap the method in an #autoreleasepool. that will make it 99% percent sure it is being deallocated
-(void)methodMethod{
#autoreleasepool {
Object* o = [[Object alloc] init];
// Some logic
}
}
Both are the same.
A better solution to test your class:
- (void)testDealloc
{
__weak CLASS *weakReference;
#autoreleasepool {
CLASS *reference = [[CLASS alloc] init]; // or similar instance creator.
weakReference = reference;
// Test your magic here.
[...]
}
// At this point the everything is working fine, the weak reference must be nil.
XCTAssertNil(weakReference);
}
This works creating an instance to the class we want to deallocate inside #autorealase, that will be released (if we are not leaking) as soon as we exit the block. weakReference will hold the reference to the instance without retaining it, that will be set to nil.
I am pretty new to Objective-C and iOS-development, and I am currently trying to grasp how to do memory-management. My app in non-ARC btw.
This object is not declared anywhere in the code (not .h or anything) other than the line belove. Do I need to release/dealloc this object in any way to clear the space for it when I am done using it, or is this done automatically?
NSMutableURLRequest *restRequest = [[NSMutableURLRequest alloc] init];
The same goes for this one. Not sure if this is the same question, but here I don't use the words alloc & init before using it. Does that make any difference?
NSString *postLength = [NSString stringWithFormat:#"%d", [postData length]];
In this case, I am defining the object in the .h-file as well as retaining it. Does this mean that the variable will always be in memory (when initialized once obsly) unless I release/dealloc it? I guess if that is the case, that is something I should do in views when the view is unloaded?
#interface Storeage : NSObject {
NSString *deviceToken;
}
#property (nonatomic, retain) NSString *deviceToken;
In the .m-file I will alloc and use this object like in the first or second case (does not seems to make any difference).
Please bear with me if this question is stupid. I am used to low level Java-programming with GC.
Do I need to release/dealloc this object in any way to clear the space for it when I am done using it, or is this done automatically?
Since you are not using ARC, you need to manually send it a release message in order to dispose of its ownership. (Good piece of advice: don't think in terms of "freeing memory". Reference counting means that you increase and decrease reference counts, you get to own and cease to own objects, the deallocation of an object upon having lost all its references is done automatically. In other words, release does not necessarily mean deallocation.)
The same goes for this one. Not sure if this is the same question, but here I don't use the words alloc & init before using it. Does that make any difference?
It does. You only own objects that you create using alloc, new, copy, mutableCopy or reference using retain. You do neither one here, so you don't have to worry about releasing it either. (Technically, it's an autoreleased instance that will be returned, the run loop will take care of it.)
In the .m-file I will alloc and use this object like in the first or second case (does not seems to make any difference).
Make the difference between instance variables and properties. A property setter method, if declared as retain or strong, will retain (increase the reference count of) your object. But that's true only if you use the accessor method, and not when you access the instance variable directly. If you wrote this:
variable = [[SomeObject alloc] init];
then you need to release it just like you would do with any other (local) variable:
[variable release];
If you use the accessor method to set it:
self.variable = [[[SomeObject alloc] init] autorelease];
then you have to use autorelease when creating it (else it will have a reference count of 2 and you'll leak memory).
In both cases, you can also use self.variable = nil; to relinquish ownership. This only works for properties.
All this radically changes with the introduction of ARC, which I don't explain here for three reasons:
I'm not an ARC expert by any means;
I'd like to encourage you to learn MRC (which you seem to have the intention to) perfectly before trying ARC;
It was not the question.
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.