Core-data raises "The file has been changed by another application" - macos

When changing data in my core-data application, a error message comes up:
The document “xyz.sqlite” could not be saved. The file has been
changed by another application.
In fact, there is no other application that has changed data. I observed in addition, that the undo management is not working well then.
Probably, I should not use more than one (unique?) Arraycontroller bound to the managedObjectContext for one entity ?
In my app, I use a classical master-detail relationship setup with 2 controllers for each entity - and 2 table views to display the data.
But, in addition I want to present a list of all details, where I can change the master. Therefore, I am using another Array controller bound to the same managedObjectContext. This one does not have a content set to the master, so it will have all detail objects. Using this approach makes it easy to manage the relationship in the associated tableview (by simply binding "selected Object" to the relationship of the detail) - but it seems to impact the app.
Does anybody else face this issue ? Any idea is welcome !

Core Data on the Mac has never dealt well with multiple programmatic changes to the underlying data, especially in document-based apps. See, for example, autosavesInPlace causes New Document save to fail.
I think you're on the right track by using the same MOC for all of your views. If you use multiple MOCs, you ave the risk of getting the data out of sync between views. Using Cocoa Bindings on the array controllers ought to be keeping everything in sync.
Is there a situation where you're making programmatic changes to the data in the background? Those should probably be done in a child of the viewContext. Or take other steps to make sure they get synced to the viewContext.

Related

Dealing with NSManagedObjects when using MVVM

I've been struggling with a good answer to this one for a while:
How do you deal with NSManagedObjects as the Model in MVVM?
I've tried a few different approaches:
Retaining a copy of the NSManagedObject on the ViewModel — although this seems a bit dangerous to me, with the potential for threading issues
Unpacking the NSManagedObject into the properties I actually use on the VM via an -initWithModel: method — this would mean I no longer receive any updates to the NSManagedObject after the initial initialisation
Retaining a copy of the NSManagedObject's NSManagedObjectID, and using an NSManagedObjectContext specifically for each ViewModel instance to retrieve and monitor a private NSManagedObject and it's attributes — this seems a bit heavy to do this for every ViewModel instance (and potentially quite fragile)
None of these seem ideal. I have an idea in my head that it might be best to combine passing in an initial NSManagedObject instance via -initWithModel:, but only retaining the NSManagedObjectID, then listening for core data save notifications and weeding out any that don't relate to the retained object ID.
What I would do, and I don't know if this is necessarily the best practice, is pass in the model and then bind properties of the view model to (possibly mapped) properties on the model. That way you get updates through the view model. It does leave a little bit open to threading problems, but you can use deliverOn: to ensure that updates are always delivered on the main scheduler.

Model view advice needed

I have been stuck for so long on this and just can not get my head around the concept. I cant retain any data outside my first page on my apps, every-time I push to another view I lose all my data entered in text fields or any pictures imported. This means I have do do everything on the first page as that the only page that dosent destroy data as soon as i move away from it.. Surely there must be an easier way to do this...can someone point in the direction of a real beginners guide to model views, ive read Apple's documentation on this and find it no help at all, ive read up on here, and googled it and really am running out of ideas now
You are storing your data in the "Controller" level. Like the "View" level these come and go and are not a good place to store data long term. For longer term storage you want to keep you data down in the "Model". You can think of the three tiers this way.
The Model is the data (both volatile and permanent) and business rules.
The Controller is business rules, data interpretation to and from the view to the model, and user interaction management.
The View is for data output translation to meaningful information and user response interpretation.
Controllers (View Controllers) should only hold enough data to do their job and should never be considered to hold data any longer than is necessary. This is why the original view controller is the only one that keeps the data. It is the "Root" view controller and is not removed since it is the bottom view controller. When you "push" another view controller it is temporary because it will be "popped" back off and deallocated. Consider keeping your data (even for you root view controller) someplace else where you can get to it. Maybe in the App Delegate, Core Data, or a custom class that simply manages the data you need. Ensure your Model and Controller object can get to the data and you will have consistent data.

How to best represent database views/summary info in "3-Tiered" application

This is basically asking the same question as in How to handle views in a multilayer-application. However, that post didn't receive much feedback.
Here's the problem: we have built a 3-tiered web application with the following tiers:
-Data Access (using repositories)
-Service
-UI (MVC 3)
DTO's are passed between the UI (Controller) Layer and Service Layer. Heavier Domain Models, containing a lot of domain-level logic, are passed between the Service and Data Access Layers. Everything is decoupled using IOC and the app follows SOLID principals (or tries too) --a big happy decoupled family!
Currently the DTO->Domain Model and Domain Model->DTO conversion happens all in the service layer.
So, finally to my question:
We are going to need to start displaying more complex read-only subsets of information, (i.e. summary views joining multiple entities doing rollup totals, etc). So what is the best practice for representing this type of read-only data in the n-tiered system? Having to map read-only Domain Model types to DTO types in this case doesn't make sense to me. In most cases, there would be no difference between the 2 types anyway. My thought would be to "break" the layering boundaries for these read-only types, having the Data Access Layer serve up the DTO's directly and pass those through to the Service Layer and on to the UI.
Can anyone point me in the right direction?
Much Thanks!
Your thought on breaking the layering for reading and then displaying values make sense completely. After all, the architecture/design of the system should help you and not the other way around.
Displaying report-like data to the user should be queried simply from the database and pushed to the view; no domain/dto conversion, especially if you're in a web app. You will save yourself a lot of trouble by doing this.
Personally, I had some attempts to go through these mappings just to display some read only data and it worked poorly; the performance, the unnecessary mappings, the odd things I had to do just to display some kind of report-like views. In this case, you'll likely have your domain model and a read model. You can look up CQRS pattern, it might guide you away from thinking that you want to use the same data model for both writes and reads.
So, to answer you question, I believe that in this case the best way would be to skip layering and read DTOs directly from the database through a thin layer.

Adding non-model nodes to an NSTreeController

I have an NSTreeController that manages an entity is a core data model and an NSOutlineView that displays this tree.
I would like the tree to display some special nodes that do not correspond to entities in the underlying core data model. How would I go about doing that? Should I subclass NSTreeController?
Keep in mind you don't have to use NSTreeController even with Core Data. I've always avoided it since it had a pretty bad reputation back in 10.4, even though I heard 10.5 improves things somewhat. In any case, using NSOutlineView's data source methods will give you full control over what's included in the UI. Subclassing NSTreeController might work, but it'll be more challenging than if it were an array controller because it uses shallow proxy objects, not your actual core data entities.

Syncing a Core Data Model With A Web Service

This problem has been kicking my butt for a few days now.
I have a web service that serves XML that looks like this:
<levels>
<level>Level 1</level>
<level>Level 2</level>
<level>Consulting</level>
<level>Office Support</level>
<level>Learning</level>
</levels>
This data needs to go into an entity in my Core Data model so that they can be used by my application. I've been able to parse them into the model just fine, my problem arises when one of the levels changes. I can create, read, and delete, but I can't figure out how to update because I need to maintain the relationships that exist with other entities in my model. I come from a strong PHP and MySQL background so my first instinct was to add a key to the model that I could use to relate, but since Core Data isn't really a database it feels wrong, and I know there must be a better way. I've searched Google a bit and could not find any answer. Am I on the right track with the key or does Core Data offer something I am missing?
I'd need more information to understand exactly how your model works, but in general I don't think there's anything wrong to adding your own unique key to a Core Data model. I'm doing the same thing for one of my applications, I keep a UUID on each object for syncing with an iPhone application.

Resources