access appdelegate's managedObjectContext in ArrayController of Document - objective-c

I am just learning some Core Data and have run into an issue with the idea of having and being able to access separate stores for application-wide and document-only data.
I have a document based application that currently uses some of the entities within a managedObjectContext to populate a table via an NSArrayController.
However, some of these entities should be application wide (part of the experience for all documents - e.g. like data for buttons representing tools that are commonly used)
So for this reason, I pasted in the AppDelegate code for the non-document based application, which creates a separate, application-wide store and managedObjectContext, for the application. What I want to do is to access this MOC within each NSPersistentDocument (readonly) via an Array Controller (as before) to populate the table view of each opened document.
How would this best be done? And if this is not the way to populate a TableView that appears in each document from an application-wide MOC, which way should I look for?
P.S I am working in Swift, but am familiar with Objective-C - Thank you for any help!

According to Apple you should pass your MOC to the controller. From Core Data Snippets. Note the last two paragraphs.
By convention, you get a context from a view controller. You must implement your application appropriately, though, to follow this pattern.
When you implement a view controller that integrates with Core Data, you can add an NSManagedObjectContext property.
When you create a view controller, you pass it the context it should use. You pass an existing context, or (in a situation where you want the new controller to manage a discrete set of edits) a new context that you create for it. It’s typically the responsibility of the application delegate to create a context to pass to the first view controller that’s displayed.
A view controller typically shouldn’t retrieve the context from a global object such as the application delegate—this makes the application architecture rigid. Neither should a view controller create a context for its own use (unless it’s a nested context). This may mean that operations performed using the controller’s context aren’t registered with other contexts, so different view controllers will have different perspectives on the data.
Sometimes, though, it’s easier or more appropriate to retrieve the context from somewhere other than application or the document, or the view controller. Several objects you might use in a Core Data-based application keep a reference to a managed object context. A managed object itself has a reference to its own context, as do the various controller objects that support Core Data such as array and object controllers (NSArrayController and NSObjectController in OS X, and NSFetchedResultsController in iOS).
Retrieving the context from one of these objects has the advantage that if you re-architect your application, for example to make use of multiple contexts, your code is likely to remain valid. For example, if you have a managed object, and you want to create a new managed object that will be related to it, you can ask original object for its managed object context and create the new object using that. This will ensure that the new object you create is in the same context as the original.

Related

MVC: Controller keeps array of model objects or view objects?

I have a view controller placeViewController which pulls in a bunch of Place objects, and from these loads and populates a matching bunch of PlaceView objects which are then displayed as subviews to its main view.
I need to update these views periodically which requires information from the model and other places to be pushed into the views
How should I properly structure this?
Keep an array of Place objects and give the model a PlaceView property to store pointers to the views
Keep an array of PlaceView objects and give the view a Place property to store pointers to the places
Keep both arrays and use a lot of indexOfObject objectAtIndex to jump between them
Some other way??
I need to update these views periodically which requires information
from the model and other places to be pushed into the views
You should really focus on an ObserverPattern. Yours views register to "notifications", and when changes are made, your registered views are notified.
http://en.wikipedia.org/wiki/Observer_pattern
You still can use NSNotificationCenter, but it will not futfill your needs since you need yours views make update per Place object (paired like a dictionary). So i recommend you to implement your own.
It will loose coupled because your controller will just only make glue between the observer and your views, and all the "logic" will be handled by the observer.
Well basvk got the answer in his comment but hasn't posted an actual answer for me to mark correct.
So here it is: "I would create a NSMutableArray with PlaceView objects. And the PlaceView class holds a #property Place *place"

Access the same object inside two different nib files

I want to know how the same reference of an object of a particular class can be accessed inside two different Xibs.
I understand that by creating an object reference for the class inside each xib creates different objects. Even when using AppDelegate its creating different objects.
What I want to achieve is that referenced object inside both the xibs should be the same (so that I can use the object as the datasource of two different table views for instance.)
Only create the object once, and put it somewhere you can get to it from both classes. For instance, you could create the object as a property of your application delegate. Then add
AppDelegate *app = [[UIApplication sharedApplication] delegate];
to your classes (after importing AppDelegate.h) and access the object with app.objectName.
The other answer will work but it's a bad design.
You should stick to the tell don't ask rule. Give your objects the dataSource you want them to use, do not have them asking for a dataSource, which is actually a nasty global.
The other issue is your understanding of nibs. They store an object graph, when a nib is loaded the graph is un archived and each object in it is instantiated. If you have two of the same objects in the graph then you will end up with two instances not two references to one instance. It is the same for when you drag out multiple views, you end up with multiple instances of UIView (and subclasses) which is exactly what you would expect.
It's well worth the effort in learning the boundaries between what you can/can't do in a nib and what you have to do in code and how they all fit together.
Interesting !
Try using singleton approach, check out this link http://www.duckrowing.com/2010/05/21/using-the-singleton-pattern-in-objective-c/
Using this approach, you can create an instance which will be available throughout the application life cycle

iOS ARC with when two objects need a pointer to the same thing

I'm going through my code to make sure that all of my properties have the proper weak/strong modifier and I ran across this situation which I don't know what to do with. Keep in mind that I'm fairly new to iOS programming.
I have a normal MVC hierarchy where my controller creates an object called FieldManager. This FieldManager is used by my controller to dynamically create textfields. However, this FieldManager also needs to be used by the controller's model to periodically query the manager to find out information about the fields (such as is it required, should it's text be capitalized...etc).
So to summarize, I have a controller which creates an object that is used both by the controller and the controller's model. Therefore, I don't know if I should make the model's reference to FieldManager a weak property or the controller's reference to it a weak property. It seems that I should make both weak properties, otherwise FieldManager will get released. What should I do?
Thanks.
Things like that should belong to your model, so the way to go is to have a datasource.
Your controller asks the datasource to create and return the textfields, the datasource contacts the model and asks for a field manager for that model.
That's the way I would do it...

Should we use Interface Builder in need of dynamically created UI?

I'm currently thinking of project, which is basically interpreting data from many abstract data sources.
So the communication within application is like this
[UI] <-> [Controller / Delegate] <-> [Subclass of Abstract Data Source]
which is basically the MVC pattern. What is my problem, that each [Subclass of Abstract Data Source] can use only limited amount of [UI], so the flow is basically this:
Create instance of Data Source (DS)
Get list of possible UI's from DS
Create UI chooser and instantiate preset UI
Let DS modify UI
Fill UI from DS by predefined handler method
Example UI's are NSTableView, NSOutlineView, NSCollectionView, etc.
So I basically need to change column names, order, style of controls, ... without possibility of having unique NSWindow designed for each Data Source
Now the question:
If I need dynamic UI creation and custom data handling logic (no bindings to Core Data, or so), should I (and is it even possible to) use InterfaceBuilder or should I implement all view logic programatically?
Use whichever you favor. Any variations/dynamic areas can be represented/handled by the controllers. In a way, that means that I recommend moving the dynamic portions to code to controllers -- but you can still use XIBs for common high level design, if you choose.
Therefore, when a view is not suitable for a singular data representation and is used for multiple, the implementation/variations can be moved to the controller domain. When an implementation/definition applies to all, then you can define that in the XIB or in the program -- wherever you prefer to put it. In that case, you can use XIBs (or code) for invariant (skeletal) views.

Core Data: When and where are Entities loaded in the first Place?

I have a question about Core Data. When starting my appliction, when is my data (which is stored automatically by Core Data) loaded into the NSArrayControllers? I want to modify it in the first place before the user can interact with it.
To be more specific: I have an NSArrayController for the entitity Playlist. Before the user can add new playlists or interact with the app at all, I want to modify the playlists programmatically. I tried windowControllerDidLoadNib: in my NSPersistentDocument (MyDocument.m) and awakeFromNib both in my NSPersistendDocument and the NSArrayController, but when I check in these methods with [[myArrayController arrangedObjects] count] I get 0 as result (the array controller's content is empty).
However, I actually have data stored and it is displayed to the user. I just do not know when and where I can modify it in the first place.
Thank your for any help.
Data is never "loaded" into the NSArrayController. The array controller is not an array itself. It does not contain or otherwise store data.
Instead, the array controller queries the object it is bound to for specific pieces of data only when that specific data is needed. This is especially true of Core Data in which managed objects are only fully instantiated when their attributes are accessed. The array controller moves data from an array type data structure to another object (usually an UI element.)
If you want to modify an existing store before it displays in the UI, you need to process the data before the array controller used by the UI is even initialized. If you're using NSPersistentDocument, then you can override readFromURL:ofType:error: to fetch and modify all your objects when the document is first opened. Alternatively, you can override the window controller's windowWillLoad or showWindow methods.
Regardless of where you do it, you must fetch all the managed objects you want to modify. You could programmatically create an array controller to do this but a fetch request is easier to micro manage if you have a large number of objects to modify.
You could try observing the "arrangedObjects" keypath of the controller and adding some logic to work that your array controller has been populated for the first time.
Another possible hook is implementing the awakeFromInsert/awakeFromFetch methods of your managed objects.