Is a property reference to an NSManagedObject unsafe? - ios

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.

Related

How memory management will work in Model class(Swift or objective C)

I have a model class which has below properties.
#interface CountryModel : NSObject
#property (nonatomic) NSInteger id;
#property (nonatomic, strong) NSString *country;
#property (nonatomic, strong) NSString *dialCode;
#property (nonatomic) BOOL isInEurope;
#end
I'm getting the below data from web service.
{
"id": 123,
"country_name": "India",
"dialCode": "+91"
}
Then I'm binding values to the array, Now my question is how memory management will work for the model class? Because there are few has a strong reference. Can anyone explain me.
Simple answer: automatically (provided you haven't disable ARC)
Slightly longer answer (provided you haven't disabled ARC):
When you assign values to the properties country and dialCode of an instance of CountryModel then that instance will have strong references to the referenced NSString values.
If you assign a new value to either of these properties then the previous strong reference will be dropped and replaced by a strong reference to the new value.
When the instance of CountryModel is no longer strongly reference by anything then the strong references it contains will be dropped.
When a strong reference is dropped if there are no other strong references to the reference object then that object becomes reclaimable and the memory it occupies returned to the available memory pool.
Note: if an NSString reference refers to a literal string then the literal string itself is immortal and will never be reclaimed. If you are trying to gian an understanding of when memory is released by monitoring memory usage, tracking dealloc calls, etc. do not use literal strings as your test objects – it is best to use a user-defined type.
But I've disabled ARC... Then memory will get reclaimed when you manually instruct it to be. If you're getting leaks turning on ARC is your best choice, if you cannot then you've some debugging to do!
HTH
Addendum after comment
Trying to follow reference counts and expecting them to match with actual executing code doesn't work well as there are often references you do not know about in compiled code. For this reason you will see many writers discouraging tracking reference counts.
Instead think in terms of strong references making an ownership stake in an object, and as long as there is an owner the object survives.
This might seem to be essentially the same thing, but there is a subtle difference in how the two are viewed: the reference count belongs to the object; while the strong reference attribute, which asserts an ownership stake, is part of the belongs to the referencing variable.
In your comment example a has an ownership stake in the CountryModel object it references - the only ownership stake you have so far created to that object. The CountryModel object has ownership stakes in the objects that country and dialcode reference, but may not be the only such stakeholders – in that fragment we've no idea what other reference variables assert an ownership stake in the objects those two variables reference.
Later when you create temparray the object reference stored in a is copied into the array and temparray claims and ownership stake in the referenced CountryModel object – while a continues to assert its own ownership stake as well. So now you have two variables you have created asserting an ownership stake in the CountryModel object.
A similar explanation applies to b & c.
When there is no ownership stake claimed by any variable/property over an object then that object can be destroyed. As part of that destruction any variables/properties that are part of that object are destroyed and any ownership stakes they asserted over references stored in them are withdrawn.
If that process results in more objects having no more ownership stakes asserted over them then those objects too can be destroyed; the process continuing to destroy unwanted objects until the only remaining objects are those where some variable/property asserts an ownership stake over them.
HTH more than it confuses!

Is it possible to observer a NSMutableArray from different class?

I'll try to summarize this as succinctly as possible:
I have three classes: a ViewController, a ViewModel, and a DataSource.
The ViewController creates both the ViewModel and DataSource. It then proceeds to "configure" the DataSource with a NSMutableArray that was initially created by and is owned by the ViewModel.
I'm aware that by implementing the appropriate indexed accessor methods I can make the NSMutableArray property KVO compliant so that my ViewModel can observe its changes.
However, what I want to do is observe the changes from my DataSource.
When it is configured the DataSource, "sets" the NSMutableArray to its own "objects" property (weak, strong, copy???). Whenever the NSMutableArray is updated via the ViewModel (which does the fetching from the server), my ViewModel is made aware of the changes. But, I can't seem to be able to observe these changes from the DataSource.
Any suggestions?
(Also, not a priority, but does anyone know of a way to do this "reactively" with RAC?).
Yes, it's possible to observe changes to an array property of one class from another class. I've done it. It's been a long time, and I don't have the code at hand, so I can't give you specifics, but it is indeed possible.
It's fragile, since if the listening object gets deallocated without removing itself as a KVO observer, you crash.
This sort of KVO observation seems like bad mojo to me. It creates fairly tight coupling between your classes, and makes the observing class dependent on implementation details of the observed class.
If I were to do this again I would probably use KVO within the class that owns the array, and then broadcast a notification, use a callback, or use some other method to notify the interested external object about the change that does not have such tight coupling.

Realm and iOS Retain Cycles

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.

Core data design patterns

For my first IOS app I plan to incorporate CoreData however I'm a little unsure about the correct design pattern I should use.
In my app delegate I have the following 3 properties.
#property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
#property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
#property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
I feel the best way to use these objects are to inject them into the constructor of all the relevant view controllers that need to access data from inside CoreData.
The cleanest way I can think of for that would be to create some kind of Repository class for each table I have in my data model which will house the above 3 objects and provide helper methods for accessing the tables data e.g. fetchAllTeams(). These repository classes can then be injected into the relevant view controllers instead of injecting all 3 objects above.
Does this sound like the correct thing to be doing in the world of CoreData & Objective-c?
Also whats the best way to create these repository classes, should I remove the default core data code and properties from the appDelegate (generated automatically) and place them inside an abstract repository class.
Should each instance of a repository have its own version of NSPersistentStoreCoordinator, NSManagedObjectModel and NSManagedObjectContext or should a single instance of these objects be shared among all repository instances passed in by the appDelegate.
Firstly, the base code that a Core-Data sets you up with can make the whole thing very confusing. The thing to understand is that Core-Data is a kind of wrapper around a variety of database technologies (sqlite, binary, xml) and by doing this, relieves you of the need to directly touch the database. The main class you are going to worry about in the beginning is NSManagedObjectContext. Think of it as a snapshot of the underling database which you can modify as you please and when you are done write that NSManagedObjectContext onto the database. The other classes you have there are really only needed for more fine-grained, low level control, and since this is your first app, best to leave those alone. You should read this, it is large, but you will gain a lot of understanding from it, especially how everything connects and their role.
To summarise though:
Really you only need to pass around the NSManagedObjectContext
You can do this my making an instance variable in every View Controller, OR,
You shouldn't go making more than one per app, unless you really need to, and then you need to make sure you merge them back together
You don't really need to create a repository of all the objects because NSManagedObjectContext does this for you...kinda... it will load objects into memory conditionally, there is a lot to this but the place to start is learning what a fault is (all in Apples documentation under NSManagedObjectContext or NSManagedObject)
think about what your objects represent and do. You can subclass NSManagedObject to represent your Core-Data object and place logic and validation inside of it - super handy.
Look into classes like NSFetchRequest and NSPredicate which are the two core classes for getting objects out of the NSManagedObjectContext.
Look into classes like NSFetchedResultsController which can tie very nicely into UI objects like UITableView.
Finally, Core-Data is a beast, and often you find yourself repeating common tasks all the time. You should look into this excellent framework which adds all sorts of helpers (like an easily accessible instance of NSManagedObjectContext, and one line object fetching, creating, deleting).
With regards this bit, my two cents...
Also whats the best way to create these repository classes, should I remove the default core data code and properties from the appDelegate (generated automatically) and place them inside an abstract repository class.
I'd definitely take out all the code that Xcode generates from the app delegate and put its in its own class. This might be a good read in explaining the basic core data stuff: http://commandshift.co.uk/blog/2013/09/07/the-core-data-stack/ (via #jrturton).
Should each instance of a repository have its own version of NSPersistentStoreCoordinator, NSManagedObjectModel and NSManagedObjectContext or should a single instance of these objects be shared among all repository instances passed in by the appDelegate.
You typically only have one persistent store coordinator (another good post here on that).
You add models to the coordinator, and also persistent stores. You can have multiple managed object contexts on a coordinator if you like.
A good example is a master detail style structure, you have a table view controller (backed by a fetch results controller), this uses the shared instance of the managed object context. When selected a managed object in the table, you pass this object into your detail view controller when creating it. You don't need to pass through, or use the shared context as that managed object will have its own managedObjectContext.
You can even create further child contexts from this if you like - think of this as a temporary context, you can change any objects registered in this context, and if you change your mind and don't want the changes any more you can just ignore and not save the child context.
Unless you have no way of accessing a managed object, or are at the top of the stack you can use the shared context. Keeping the use of shared context to only when its needed, I personally think keeps things simpler as you don't have to worry about what's (and where) using the global shared context through out your app. (Granted the shared context will be the base one anyway, but using a managed objects own context will mean when you save any changes to that context you know that that object will be effected).
Also to deal with simpler accessing and creating of managed objects I recommend mogenerator, there's a good post here about setting it up.

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".

Resources