Realm and iOS Retain Cycles - ios

Does realm properly handle entities that have a parent-child relationship (e.g. the child holds a reference to the parent)? The documentation states that Realm ignores the property modifiers (nonatomic, weak, ...), so I basically don't have control of this.

For standalone objects (i.e. objects created with [[MyClass alloc] init] which have not been added to a Realm afterwards) the normal rules apply, and you'll need to use a weak property to break the retain cycle if you're constructing graphs of standalone objects.
For objects persisted in a Realm, accessing RLMObject-subclass properties actually creates a new object each time rather than caching the accessor object. This means that the objects never actually hold references to any other in-memory objects, so there can't be a retain cycle.

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.

CoreData: concurrency and relationship strong reference cycles

I'm importing a chunk of data into CoreData, using a subclass of NSOperation to do so. The operation creates its own NSManagedObjectContext (with concurrency type NSPrivateQueueConcurrencyType) specific to the run method of the operation. During import, I need to create a relationship between an instance of NSManagedObject in the NSOperation object context (we'll call it Object A) and another object in another NSManagedObjectContext (Object B).
The relationship establishes successfully, but I'm running into a relationship strong reference cycle (Apple docs here) that I can't seem to break without compromising the integrity of the relationship. Not breaking the cycle isn't fatal, but it causes a balloon in memory footprint during import that is unacceptable. Using refreshObject:mergeChanges: and setting mergeChanges: to NO (as is typically recommended for breaking relationship strong ref cycles) screws with the data; it doesn't save correctly, and in some cases doesn't save at all.
How do you break relationship strong reference cycles when working with CoreData concurrently?

How to know which attributes to use with different properties? [duplicate]

Can someone explain to me in detail when I must use each attribute: nonatomic, copy, strong, weak, and so on, for a declared property, and explain what each does? Some sort of example would be great also. I am using ARC.
Nonatomic
Nonatomic will not generate threadsafe routines thru #synthesize accessors. atomic will generate threadsafe accessors so atomic variables are threadsafe (can be accessed from multiple threads without botching of data)
Copy
copy is required when the object is mutable. Use this if you need the value of the object as it is at this moment, and you don't want that value to reflect any changes made by other owners of the object. You will need to release the object when you are finished with it because you are retaining the copy.
Assign
Assign is somewhat the opposite to copy. When calling the getter of an assign property, it returns a reference to the actual data. Typically you use this attribute when you have a property of primitive type (float, int, BOOL...)
Retain
retain is required when the attribute is a pointer to a reference counted object that was allocated on the heap. Allocation should look something like:
NSObject* obj = [[NSObject alloc] init]; // ref counted var
The setter generated by #synthesize will add a reference count to the object when it is copied so the underlying object is not autodestroyed if the original copy goes out of scope.
You will need to release the object when you are finished with it. #propertys using retain will increase the reference count and occupy memory in the autorelease pool.
Strong
strong is a replacement for the retain attribute, as part of Objective-C Automated Reference Counting (ARC). In non-ARC code it's just a synonym for retain.
This is a good website to learn about strong and weak for iOS 5.
http://www.raywenderlich.com/5677/beginning-arc-in-ios-5-part-1
Weak
weak is similar to strong except that it won't increase the reference count by 1. It does not become an owner of that object but just holds a reference to it. If the object's reference count drops to 0, even though you may still be pointing to it here, it will be deallocated from memory.
The above link contain both Good information regarding Weak and Strong.
nonatomic property means #synthesized methods are not going to be generated threadsafe -- but this is much faster than the atomic property since extra checks are eliminated.
strong is used with ARC and it basically helps you , by not having to worry about the retain count of an object. ARC automatically releases it for you when you are done with it.Using the keyword strong means that you own the object.
weak ownership means that you don't own it and it just keeps track of the object till the object it was assigned to stays , as soon as the second object is released it loses is value. For eg. obj.a=objectB; is used and a has weak property , than its value will only be valid till objectB remains in memory.
copy property is very well explained here
strong,weak,retain,copy,assign are mutually exclusive so you can't use them on one single object... read the "Declared Properties " section
hoping this helps you out a bit...
This link has the break down
http://clang.llvm.org/docs/AutomaticReferenceCounting.html#ownership.spelling.property
assign implies __unsafe_unretained ownership.
copy implies __strong ownership, as well as the usual behavior of copy
semantics on the setter.
retain implies __strong ownership.
strong implies __strong ownership.
unsafe_unretained implies __unsafe_unretained ownership.
weak implies __weak ownership.
Great answers!
One thing that I would like to clarify deeper is nonatomic/atomic.
The user should understand that this property - "atomicity" spreads only on the attribute's reference and not on it's contents.
I.e. atomic will guarantee the user atomicity for reading/setting the pointer and only the pointer to the attribute.
For example:
#interface MyClass: NSObject
#property (atomic, strong) NSDictionary *dict;
...
In this case it is guaranteed that the pointer to the dict will be read/set in the atomic manner by different threads.
BUT the dict itself (the dictionary dict pointing to) is still thread unsafe, i.e. all read/add operations to the dictionary are still thread unsafe.
If you need thread safe collection you either have bad architecture (more often) OR real requirement (more rare).
If it is "real requirement" - you should either find good&tested thread safe collection component OR be prepared for trials and tribulations writing your own one.
It latter case look at "lock-free", "wait-free" paradigms. Looks like rocket-science at a first glance, but could help you achieving fantastic performance in comparison to "usual locking".

Is a property reference to an NSManagedObject unsafe?

In the book Learning Core Data for iOS, the author creates several UIViewControllers which each have a property that refers to an NSManagedObjectID.
In example,
#interface LocationAtShopViewController : UIViewController
#property (strong, nonatomic) NSManagedObjectID *selectedObjectID;
// ... other properties and methods
#end
In this manner, he is able to pass an NSManagedObjectID from one controller to another and retrieve the associated NSManagedObject object using NSManagedObjectContext's existingObjectWithID:error: method.
Further, he doesn't ever set an NSManagedObject object directly (even if he already has a variable reference to it), nor does he keep a reference to the NSManagedObject object very long (instead, he retrieves it in each method that he needs it).
Is it unsafe (i.e. will cause crashes or lead to unexpected behavior in certain circumstances) to pass an NSManagedObject directly between controllers via a property reference, or simply keep a reference to it on a controller?
In example,
#interface LocationAtShopViewController : UIViewController
#property (strong, nonatomic) LocationAtShop *locationAtShop;
// ... other properties and methods
#end
Assuming a single, shared NSManagedObjectContext is used, so disregard issues caused by passing between multiple contexts, which isn't safe in general.
There is no reason to avoid using the managed object directly, provided that:
You only use the managed object with a single managed object context, and
You either
only ever use the managed object on a single thread or queue, or
Make sure to use performBlock or performBlockAndWait when working on a different queue.
Keeping only the object ID may be less error-prone since it makes it a lot harder to accidentally mix up contexts or queues. That may make it a better idea for less experienced developers, who are therefore less likely to screw things up. But it's certainly not wrong nor even especially dangerous to keep the object itself.
Is it safe ?
Yes, it's safe, with some caveats:
Per Tom Harrington's answer, in general it's safe to store an NSManagedObject as a property on a controller.
However, there are situations in which this can cause problems. Notably,
If the referenced NSManagedObject is deleted and its context is saved, the property must explicitly be set to nil.
If you do not explicitly set the property to nil, the next time you try to access an attribute on the object, it will cause a CoreData could not fulfill a fault crash.
Why did the author of Learning Core Data for iOS pass and store the NSManagedObjectID instead of the NSManagedObject?
The likely reasons may include:
If instead of storing the NSManagedObject as a property you stored the NSManagedObjectID, you don't have to worry too much about the object being deleted.
This is because NSManagedObjectContext's method existingObjectWithID:error: will return nil in the event that the object cannot be fetched, or does not exist, or cannot be faulted.
So, it's safer to store the NSManagedObjectID as a property than it is to store the NSManagedObject, if deletion of the object is possible.

What are the disadvantages of setting every property to strong?

As a new iOS programmer, I've had a slew of bugs to fix today, a few of them have been related to me using weak properties instead of strong.
I realise that a good programmer wouldn't have this problem and would only set the properties to strong that need to be, but nonetheless, in my newbie eyes, I can't see why I should use weak, it only adds the risk of problems.
In general, you should decide between weak, strong, assign, and copy by looking at the relationship between the class holding the property and the value of that property, and also the kind of the property being passed.
If the property being set is primitive, use assign (or do not use ownership qualifier at all)
If the property being set is a scalar, immutable object, use strong
If the property being set is a scalar, mutable object implementing NSCopying protocol, use copy
If the property being set is mutable, and the ownership is transferred to your object, use strong
If the property being set is a mutable object implementing NSCopying protocol, but the ownership remains with the caller, use copy
If the property being set is a back reference (i.e. a "to parent" property in a "child" object), use weak.
The concept of ownership is very important in reference counted memory models. This is the primary driving factor behind your decision. You need to decide where is the primary owner of an object, and give that owner a strong reference. If an ownership is shared among a group of objects, give them all a strong reference.
The most difficult situation is when objects could own each other, directly or indirectly. In this case you would be better off replacing "ownership" with "knows about", give all objects a common "top" owner who "owns" everybody, and model the "knows about" relationships with weak references.
weak and strong are very important to get right for memory management purposes.
strong will increase the reference counter for the pointer, and you effectively say that you own the object.
weak does not increase the reference counter, and the object can potentially disappear at any time. If you have a cyclic dependency, you should use weak to avoid a memory leak (two objects both having a strong reference to each other is a cyclic dependency and those objects will never be released).
You should always think about your memory management, but a good rule of thumb is that the property should always be strong, unless you positively know that it is retained elsewhere. Multiple objects can have a strong reference to the same object with no problems, as long as no cyclic references occur.
Some super basic rules of thumb:
If you want the object to stick around at least until you are finished with it, go with strong
If you can handle the object disappearing without it hurting you too bad (i.e it is the parent that created you that might be nice to know about but not super important) then use weak
if it is not an NSObject (so is an int, bool float or other primitive type) use assign.
A rule of thumb that I use is: if the object is retained somewhere else, use weak. The biggest thing for me is when using interface builder. If you have an IBOutlet, you can make it weak, because that object is taken care of in interface builder and in the XIB file

Resources