Coredata | Child Context memory Management - ios

I am creating some child context from the main context and I wanted to know do I need to release the child context?
I have a CoreData class which creates child context (this class is an arc enabled classes) but it can provide context to other classes which might not be arc classes.
- (NSManagedObjectContext *) createChildContext
{
NSManagedObjectContext *childManagedContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
childManagedContext.parentContext = [self parentContext];
return childManagedContext;
}
then some other class can get the child context
NSManagedObjectContext *context = [coredata createChildContext];
My question is do I need to release the context in this class or will it be auto managed by the arc class that created it since I am not retaining it.

This is actually a pretty interesting question, since you're mixing ARC and non-ARC. As always, though, the Memory Management Policy can help us decide what to do in this situation.
First off (as I think you already know), you don't have to release the context in the ARC class that creates it (inside -createChildContext). In fact, you can't explicitly release or autorelease it there, since the class is ARC - you can't do any manual memory management inside it.
Now let's look at the calling class. As you have it written, you do not have to release the context once you're done with it. Since you have not taken ownership of the context, you shouldn't tell the object that you're releasing it; it's not your place to give up ownership of an object you never owned in the first place.
Why haven't you taken ownership of the context? Well, as you have it written, you never:
Explicitly retained the object (e.g. [[coredata createChildContext] retain])
Assigned the object to a #property marked retain or strong
Got the object from a method starting with alloc, new, or copy
In this sense, you could think of the object being "managed by" the ARC class that created it, though that's a bit misleading; in reality, it doesn't matter who manages it, it just matters that you don't own it in the non-ARC calling class.
If you need to change that for some reason - say, you need the child context to stick around for a while, or you intend to use it throughout your class - you could consider one of the approaches listed above, where you do take ownership of the context. In that case, you would have to release it when you're done with it.
I highly recommend reading over the Advanced Memory Management Programming Guide; it has a lot of very useful things to say about dealing with object ownership, among other topics.

Related

Why is there a Weak References Between Managed Objects and the Context?

When i was learning how to use child contexts :
let childContext =
NSManagedObjectContext(
concurrencyType: .mainQueueConcurrencyType)
childContext.parent = coreDataStack.mainContext
let childEntry =
childContext.object(with: surfJournalEntry.objectID)
as? JournalEntry
// 3
detailViewController.journalEntry = childEntry
detailViewController.context = childContext
detailViewController.delegate = self
Author made some remark about passing both managed object and the managed object context to the detailViewController:
Note: You might be wondering why you need to pass both the managed
object and the managed object context to the detailViewController,
since managed objects already have a context variable. This is because
managed objects only have a weak reference to the context. If you
don’t pass the context, ARC will remove the context from memory (since
nothing else is retaining it) and the app will not behave as you
expect.
Well, ok, so then a read some official doc:
This means that in general you cannot rely on a context to ensure the
longevity of a managed object instance, and you cannot rely on the
existence of a managed object to ensure the longevity of a context.
Put another way, just because you fetched an object doesn’t mean it
will stay around.
But yet, i don't get what is true intention of making weak references between managed objects and the context? What is the goal do they pursue?
Managed object contexts usually use weak references to fetched objects to avoid the potential for excessive memory use. If it used strong references, and you did one or more fetches that found a large number of results, all of them would remain in memory for as long as the context existed. In many apps that would mean they'd never go away, because the context exists until the app exits. That could cause the app to use a lot of memory for objects it wasn't using anymore. Weak references mean that the managed objects are deallocated as soon as the app stops using them.
But you might want strong references in some cases, so there's a boolean property called retainsRegisteredObjects that makes the context use strong references instead. Use it if you like, but be careful of memory use.
Managed objects don't keep strong references to their contexts to avoid reference cycles. If they were strong references and you set retainsRegisteredObjects to true, you'd get a reference cycle. Each object would hold a strong reference to the other, so neither could be released from memory unless you set one of the references to nil.
You can think of managedObject as small and stupid object. They have a pointer to their context and know their objectId. When they need to know something they query the context. This has a lot of really neat advantages. If an entity was already queried in the context, a second instance of it will hit the row cache in the context and not hit the store at all.
Generally there are two kinds of context (for most core data setups): long lived main queue context that are always in memory, and short lived background contexts. For the main queue context you generally don't need to worry about the contexts leaving memory. They stay in memory for the lifetime of the application. The short lived context have a problem of leaving memory and also have a problem that they are not thread-safe. So generally they should be created in a block that is on the correct thread - used and then discarded and not pass out of the block.
I hope that explains it.

__autoreleasing for return value in ARC Objective-C

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.

Recipes to pass NSManagedObjects amongs UIViewControllers

Within an application it's possible to have different UIViewControllers that need to share the same NSManagedObject. I'm usually do the following:
#interface CustomController : UIViewController
#property (nonatomic, retain) ProductNSManagedObject* productManaged;
#end
Then when I istantiate CustomController I inject it like the following:
customController.productManaged = ....
once done, CustomController is responsible to release it.
This approach works well (I don't know if is it correct), but what to do when a controller need that object but it's not a direct child of the controller that has that object? e.g.
MainController -> ChildController -> SubChildController -> ....
where MainController has the managed object.
Do I have to create a lot of intermediary properties or do I need to execute a fresh NSFetchRequest or something else?
The same aspect could be applied to the NSManagedObjectContext. Searching around I've found that the context can be grabbed from the application delegate that posseses it (if any). But this approach lacks of flexibility as Marcus Zarra wrote in passing-around-a-nsmanagedobjectcontext-on-the-iphone.
Any suggestions? Thank you in advance.
I create a singleton object that contains the managed object context that will be used throughout the application. I put any supporting code related to the data (e.g., persistent store coordinator) inside this singleton and keep all of the view and controller information separated from it.
In one case, I need a managed object context for another thread. It became apparent that it would be useful to refactor and put that context inside the same singleton. Then merging between the two contexts can be done inside the singleton.
This has helped me manage my code. You might consider it.
This is a very common question (see here and here for related ones). As I wrote in the answers for the related questions, you should stay away from singletons and create a separate object that will take care of object instantiation, of creating the object graph for your application. This separate object can hold references to all shared objects and supply them to the objects being built, so that none of your regular objects has to keep a reference to something just to pass it as a dependency to other objects. See this blog post for more rationale against singleton misuse and for further pointers, especially the articles by Miško Hevery.
I have created a sample Xcode project that shows how to wire an app without singletons, keeping the coupling low and resolving other singleton issues. It’s very simple at the moment, I will add more common use cases later.

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.

retain cycle with core-data

I think I have a problem, maybe linked to a retain cycle in Core-Data.
The code is a follow, where self.image is also a NSManagedObject:
- (void)setImage:(UIImage*)image1 andThumbnail:(UIImage*)image2
{
self.image.data = UIImageJPEGRepresentation(image1, 0.85); // This is autoreleased
self.thumbnail = UIImageJPEGRepresentation(image2, 0.85); // This is autoreleased
}
Apparently, the "self.image.date =" has one retain that is never released (and I think that it is between self.image and self). Because of that the self object will never be released and hence the leak.
EDIT: so basically I have the same problem as here: https://devforums.apple.com/message/246219#246219
I use exactly the same structure where the self in the previous code corresponds to the Bar in the given link. I also have the same view controller structure. However, the refreshObject doesn't help.
I tried to use the NSManagedObjectContext refreshObject method to break the retain cycle (as suggested in Apple documentation). It has no influence on the retainCount. I'm probably not using it the right way but I can't find much information about it. If I use NSManagedObjectContext:reset: I get a crash in the root view controller when I come back to it.
Thanks!
You should not interfere with the managed object context's management of the managed objects memory.
If self.image above is a managed object and you have not written custom accessors then you have no memory management concerns from it. Any attempt to manage the context's memory manually will almost always cause more problems than it solves.
Retain counts tell you nothing except in the simplest and smallest of command line apps. Once you use frameworks like Core Data, the behind the scenes retention is so complex that the retain count often bears no relationship to what happens in your own code.
Apparently, the "self.image.date ="
has one retain that is never released
(and I think that it is between
self.image and self). Because of that
the self object will never be released
and hence the leak.
This will not happen. You do not have to kill all objects in an instance's retained attributes before killing the instance itself. If that was true, you couldn't kill an instance that shared an attribute object with a 3rd object. If they were non-managedObject instances, the self.image object can exist long after the self object dies. Only the enforcement of the entity graph by the context makes them behave different and that has nothing to do with memory management.
If you see a mysterious retain count of 1 on a managed object, that is the retain put on the object by the managed object context. As long as the context believes the managed object must exist in the entity graph, it will never release the object.
If the leak is in the Core Data stack at all, your problem is most likely in the entity graph between the self entity and the self.image entity. The entity graph is preventing one or the other from being deleted most likely by a deny or a required relationship.

Resources