So I'm building a document-based application in Cocoa and trying to understand NSManagedObjectContext. I've read Apple's "Core Data Basics" but can't wrap my head around it. In my application I created a custom CoreDataUtility class so that all of my classes can get the context via the following lines of code:
MyCoreDataUtility *coreData = [MyCoreDataUtility sharedCoreDataUtility];
NSManagedObjectContext *context = [coreData context];
I got this idea from the site "Cocoa is my girlfriend". Where I get confused is when I run my application and I create a new window (my file owner class is a subclass of NSPersistentDocument) if I make changes to the context on the new window, the view reflects the changes on the old window and as well as the new one. Based on this I'm assuming that both windows are referring to the same context or at least the same data in some way.
So my questions are:
I have the assumption that each time I create a new window a new
context is created, is this correct?
If a new context is created and they are different (I actually
printed out the memory address of the two contexts and they
addresses are different) does this have something to do with the
persistent store coordinator or persistent object store (both of
these concepts are also nebulous in my mind)?
If all documents refer to the same context is it my responsibility to
create a new context every time a document is created?
Thanks all!
I have the assumption that each time I create a new window a new
context is created, is this correct?
No and yes. Creating a new window does not create a new context, but I suppose that what you see as "a new window" is actually your action of "creating a new document". In a document based app with CoreDate you are likely to have a persistent store which creates a new context for every document by itself.
That is also the answer to your second question. The store coordinator is just the central point that manages all documents of your application. It takes care of some menu related actions, such as opening, saving and all side effects.
If all documents refer to the same context is it my responsibility to
create a new context every time a document is created?
That is not possible. One context can be related with only one file (or "store"), hence every document must have "at its minimum" one context. If you are using the template for a CoreData and Multi-document based app, you do not have to worry about creating a new context. As I said before, the store coordinator will take care of that. However as you learn more about CoreData, and specially if you do multithreading, you will have to create more than one context because because a context cannot cross threads.
Could you provide the link from Cocoa is my girlfriend where you took that code? It seems you want a singleton to store your context and usually that is a bad idea in a document based app because it is extremely easy to mess up things giving one function the context of a different document. Your application should have a good flow where the context is passed. However I always use a singleton if my application is not document based.
Related
I'm developing an iPad-app and I'm currently struggling with finding the best approach to multithreading. Let me illustrate this with a simplified example:
I have a view with 2 subviews, a directory picker and a gallery with thumbnails of all the images in the selected directory. Since 'downloading' and generating these thumbnails can take quite a while I need multithreading so the interaction and updating of the view doesn't get blocked.
This is what I already tried:
[self performSelectorInBackground:#selector(displayThumbnails:) withObject:currentFolder];
This worked fine because the users interactions didn't get blocked, however it miserably fails when the user taps on another folder while the first folder is still loading. Two threads are trying to access the same view and variables which results in messing up each others proper execution. When the users taps another folder, the displayThumbnails of the currently loading folder should get aborted. I didn't find any way to do this..
NSThreads
I tried this but struggled with almost the same problems as with the first method, I didn't find a (easy) way to cancel the ongoing method. (Yes, I know about [aThread cancel] but didn't find a way to 'resume' the thread). Maybe I should subclass NSThread and implement my own isRunning etc methods? But isn't there any better way or a third (or even fourth and fifth) option I'm overlooking?
I think this is a fairly simple example and I think there is perhaps a better solution without subclassing NSThread. So, what would you do? Your opinions please!
NSOperationQueue should work well for this task.
Another option would be plain GCD, however, if you've never worked with it, NSOperationQueue is probably the better choice since it pretty much automatically guides you to implementing things "the right way", has obvious ways for cancellation, etc.
You want to use Concurrent NSOperations to download and process images in the background. These would be managed by an NSOperationsQueue. Essentially these operations would be configured to fetch one image per operation, process it, save it in the file system, then message back to the main app in the main thread that the image is available.
There are several projects on github that you can look at that show how to do this - just search github using "Concurrent" or "NSOperation".
iOS has a really nice facility for doing background work. Grand Central Dispatch (GCD) and Blocks, but those don't let you have an object using delegate callbacks - thus NSOperation.
So you need to read up on blocks, GCD, and then look at some open source Concurrent NSOperations code. Using Concurrent NSOperations is not as simple as using blocks.
If I had this problem, I would probably go for an approach like this:
a single thread that will load the images, and causes the main thread to display results (I'm not a big fan of having thread mess around with GUI objects)
when a new directory is requested... well, it depends on how you want to manage things. Basically, a standard queue construct (condition variable and array) could be used for the main thread to tell the thread that "this directory will be needed" by passing it the path name; the thread will check the queue even when it's loading images (like after every image or so), and switch to the new directory whenever one shows up
you could make a directory-reader object that keeps all the state, and store this indexed by the path into a dictionary. When a new directory is requested, check that dictionary first, and only create a new object if there's none for this directory. That way, partially loaded directories would stick around until they are needed again, and can continue to load instead of having to start from scratch.
Pseudocode for the thread:
while (forever)
new element = nil
if we have an active directory loader
tell directory loader to load one image
if false then make directory loader inactive
lock queue condition
if queue has elements
new element = retrieve LAST element (we aren't interested in the others)
empty queue
unlock with status "empty"
else
unlock queue
else
lock queue on condition "has elements"
new element = retrieve last element
empty queue
unlock with status "empty"
if new element != nil
if directory loader for new path does not exist
setup new directory loader for new path
store in dictionary
make it the "active" one
else
make the current one the "active"
As for the directory loader, it might look something like this:
read one image:
if there are still images to read:
read, process and store one
return true
else
performSelectorOnMainThread with an "update GUI" method and the image list as parameter
return false;
This is just a quick sketch; there's some code duplication in the thread, and the way I wrote it will only update the GUI after all images have been read, instead of making them appear as we read them. You'll have to copy the current image list, or add synchronization if you want to do that.
I am developing a site using App Engine and Webapp2.
I understand the concepts of OO and more or less how they are applied in Python. However I am confused about how App Engine uses OO. When an instance of my app is created, is one instance of each class created and re-used for each user? Or are separate instances created for each user? This will decide whether I should use instance or class variables.
So to be even more specific, when should I use self. variables (instance variables) and when should I leave out self. (class variables)?
Thanks for your help. :)
I would separate the concepts of object-orientation (OO) and request handling. First and foremost, App Engine is based on a request-driven model. A request is the base for most actions triggered on App Engine.
Second of all, be aware of the differences between an App Engine instance[0], which is like a container for you application and provided by the App Engine infrastructure, and an webapp2.WSGIApplication[1], which is an object instance of a class you defined.
To simplify things, I assume your app only has 1 webapp2.WSGIApplication . Now let's start with the first request your application gets. Before that, nothing of your app exists, except the code and configuration available on App Engine machines. Once the request reaches App Engine, a new App Engine instance[0] is created. Once the App Engine instance is in place and set up, it will instantiate a webapp2.WSGIApplication instance[1]. Now you have both relevant "instances" in place, the object being a part of the container. Next, the incoming request is routed to your webapp2.WSGIApplication instance which will handle the request according to the implementation you have done.
The App Engine system will create new App Engine instances for you dependening on the load. If a single instance is not able to handle all the requests that come in, it will create a new instance(first [0], then [1] within the former) and spread the load. If that's still not enough, a third instance is created and so on. The same is true if load decreases. If you application is currently running on 3 instances, but 2 would be enough to handle the load, 1 instance will be killed. In addition, you don't know which particular instance will handle which request.
And this leads us to your second question, should you depend on instance variables. Because App Engine creates and kills instances as it seems appropriate and you don't know which instance handles a request, you should always assume instances to be stateless. While it is not always the case, potentially every request can be handled by a completely new instance.
If you need to have state, use memcache (volatile) or datastore (persistent) or some other data backend (blobstore, files API, and so on).
[0] https://developers.google.com/appengine/docs/adminconsole/instances
[1] http://webapp-improved.appspot.com/guide/app.html
PS: people do use instance memory to optimize requests, but beginners who start to learn about App Engine should consider this an advanced technique.
Two views in my application need to load same information when restoring state. My idea was, to avoid saving it twice, to have one view create another in init orcreatePartControl if it wasn't created yet. However,
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView(...)
doesn't work there, as getActivePage() returns null. Is it possible to work around this?
Delegate to a manager or service to load/maintain/save the shared state. That will ensure the first access initializes your information. When the view is instantiated just go to the manager and retrieve the information. If the user never instantiates your view, then you never had to do the extra work.
In the general case, you can't create/instantiate one view while creating/activating another view. Eclipse won't allow it, and will generate ERRORs in the error log.
EDIT:
3 standard persistence patterns I've seen used (and/or misused :-) are:
1) Have your plugin get its state location and simply serialize you state out there. (location provided for free if you subclass org.eclipse.core.runtime.Plugin) You can do it in your activator stop(BundleContext) method. You can uses classes like org.eclipse.ui.XMLMemento to serialize to/from XML if you don't already have a solution.
2) if you subclass org.eclipse.ui.plugin.AbstractUIPlugin you can use org.eclipse.ui.plugin.AbstractUIPlugin.getDialogSettings() to store your state. Potentially a little bulky as you would have to keep it up to date.
3) have your common manager update a preference, potentially using another serialization technique.
Currently I am struggling with a Entity Framework issue. I have a wcf service that sits on top of the ef framework, and allows queries to the framework. At some point the user is able to request a file from the framework. The files are referenced by solution entries, so when you request a file from a solution, the reference is loaded to gain access to the file store.
That all works fine, but from that point onward, whenever you do another query that returns that solution entry, the whole file gets attached to the return result. I need some way of detaching or unloading the reference, such that the result entries will only contain an unloaded reference to the file store again.
I have tried to create a new context and query that context to retrieve information from, but when I do that, the entity in the original context is also changed.
I have tried to detach the entity from the original context and then query from the new context. That does not work either.
I have found one way of doing this. For all the non file-download queries, I detach the result entity, and send that over the wire. I am not sure if that is the best way to go about it though.
I hope someone might be able to provide some insight, thanks for the effort.
The issue you are experiencing is probably do to Change Tracking, which is on by default.
Possible Solution:
Disable Change Tracking with MergeOption.NoTracking
using (MyEntities _context = new MyEntities())
{
_context.Widgets.MergeOption = MergeOption.NoTracking;
return _context.Widgets.ToList();
}
This article may help to point you in the right direction on how to handle this issue if the solution above does not work.
I struggled with a similar issue recently. The problem was the result of the context maintaining a reference to the object I was using (obviously). Every time I made a change to an object of the same type, even when obtained with a new context (so I thought), the object was being changed.
With help from one of my peers, we determined the context was hanging around due to the way I was registering it with my IoC container (lifestyle per web request). When I changed the lifestyle to transient (which definitively provided a new instance) then changes to objects of the same type were unaffected.
Hope this helps.
We are using NHibernate to manage our persistence in a complex modular windows forms application - but one thought keeps bothering me. We currently open a session on launch and open all objects through that session. I am worried that all loaded objects get loaded into the NHibernate session cache, so that they cant be garbage collected, and ultimately we will end up with the whole database in memory.
This never happens with web applications because web page requests (and even better Ajax requests) represent the perfect short lived transaction so a session can be opened and closed to handle each request.
However if I load an tree of objects in my forms application and put then into a navigation pane on the screen they may stay their for the life of the application - and at any point the user may click on them, resulting in our code needing to navigate the object relationships to other objects (which only works within an NHibernate session).
What do StackOverflow readers do to keep the benefits of NHibernate without the issues I describe?
Ayende and company usually recommend using a session per "conversation". This usually makes the session lifetime last for very short operations, so it behaves more like a web app.
For your tree case, you can use Bruno's solution #2 just fine. The objects can be lazily mapped. Then, every time you need to access a child collection, you start a conversation and reconnect the parent via ISession.Lock. Then when the databinding is done, close that session. Not too much overhead to maintain, just a few lines of code in any form that needs to carry a conversation; you can extend Form and the controls you're using to do this automatically if you're feeling sassy.
The tricky part, then, is concurrent edits from different sessions. Let's not go there!
I open a session when I need one, and I'll close it when I know that I won't need it anymore.
More specifically, for instance, if I have a form which lets me edit Customer information for instance, I'll open a session when the form gets instantiated, and I'll close the Session when the form is closed.
When I have 2 instances of that form open, I also have 2 session open.
I can see a couple of alternatives:
Eager-load the object tree (which, from what I can gather from the documentation is the default)
Detach the objects, intercept the "click" event, and load the data from the database then, with a new session. This one forces you to take care of collections by yourself, instead of relying on nhibernate, which may fall outside of the scope of the question (which asks for the benefits of NHibernate, one of which is collection management)
You can take a look to my posts on how to use uNHAddins to work with session per conversation in a Windows Forms application (uNHAddins is a project with some additionsns to NHibernate led by Fabio Maulo, current NH Lead)
The first post is this
http://gustavoringel.blogspot.com/2009/02/unhaddins-persistence-conversation-part.html
From there you have links to uNHAddins trunk.