I am trying to set up the binding between Core Data, NSArraycountroller and a NSTableView. To get a NSManagedObjectContext for the NSArrayController. I dragged an NSObject in the IB, and named it after the appDelegate and then set up the binding of objectContext between appDelegate and the arrayController.
However, whenever I tried to run the app. I get this error message:
The error message:
The managed object model version used to open the persistent store is incompatible with
the one that was used to create the persistent store
And then followed by another error message:
Failed to initialize store.
I googled around, most of the people can solve this issue by clean their project or delete the files under ~/Library/Application Support/AppName/.. But I don't have luck with those.
Another thing is that, I desperately want some good tutorial on this topic (CoreData+ArrayController+TableView). Can someone shed some light on this as well? I read through the chapter 11 of the book "Cocoa Programming for Mac OSX 4th version", but didn't find it really helpful.
Thanks.
Finally solved this issue. I think it has to do with Reskit. Reskit has its own managedObjectContext when bundle with CoreData. That's why it keeps telling me the two object model is incompatible. The NSArrayController should be binded to the managedObjectContext in RKManager instead of the one in appDelegate.
So I put this in the init method of view controller:
RKObjectManager *objectManager = [RKObjectManager sharedManager];
currentObjectContext = objectManager.objectStore.managedObjectContextForCurrentThread;
And point the managedObjectContext in the NSArrayController object to the currentObjectContext.
The error has to do with your managed object model; it's not related to your bindings or table view. If it happens when you run the app (vs. when you try to open a document) it's probably during restoration of autosaved documents.
Try deleting anything related from ~/Library/Autosave Information and seeing if that fixes the initial problem.
Related
I just upgraded Xcode to 8.0 (8A218a) and am converting my project in Swift 2.3 to Swift 3.0. The only issue left now is this error:
"Exception while running ibtool: Cannot find value transformer with
name UTIToIconTransformer"
The UTIToIconTransformer is defined something like:
#objc(UTIToIconTransformer) class UTIToIconTransformer : ValueTransformer {
// ...
}
The code worked fine when it was in Swift 2.3. The binding using this value transformer is set like this:
If I remove this binding, the app runs, and the row titles are shown correctly.
I have tried calling NSValueTransformer.setValueTransformer() in the app delegate's +initialize(), in applicationDidFinishLaunching and in the value transformer's +initialize(), as suggested here, here at StackOverflow and here at NShipster (Though I don't think the statement of "Typically, the singleton instance would be registered in the +initialize method of the value transformer subclass, so it could be used without further setup." complies with the Apple's doc.), all without success.
In the Apple's doc, it says
Value transformers are typically registered by an application’s delegate
class, in response to receiving a initialize: class message. This allows
registration to occur early in the application startup process, providing
access to the value transformers as nib files load.
Availability in Interface Builder
Your NSValueTransformer subclasses are not automatically listed in the
Interface Builder bindings inspector. When inspecting a binding you can enter
the name that the value transformer is registered with, but the functionality
will not be present in Interface Builder’s test mode. When your application
is compiled and run the transformer will be used.
But registering in the AppDelegate's override class func initialize() didn't help. In Xcode 7 and Swift 2.3, it even worked without the registration.
Finally I solved the problem by removing the NSOutlineView from the storyboard and setting up a new one.
I have another project which also has an outlineview binded with an NSTreeController, and that project has no problem after the Xcode 8.0 upgrade. Then I tried creating a new ValueTransformer with a new name, with no luck.
I guess there may be something wrong with the storyboard, so I tried recreating the outline view. Then Xcode doesn't complain that it can't find the transformers!
i have to port existing iOS code (which is using NSFetchedResultController) to OS X, can u please give me some code snippets on how to get contentWillChange and contentDidChange events using NSArrayController.
You don't. NSArrayController does all that, and more, when you bind it to a tableview and set its entity type properly.
Using bindings you can remove all of the table data source code that you had for iOS.
If you want to recreate NSFetchedResultsController, you need to listen to managed object notifications and act on them in the same way, but bindings is much easier.
After some 'cleaning' of a working app, the main window appears as designed in the MainWindow.xib.
I deleted a MainWindowViewController object in IB. (was beneath Font Manager)
MainWindow.xib has it's Custom class set to MainWindowViewController
The table uses Content Mode - View Based
The two required methods ARE included in that implementation file
included in header file
Table view connection has been made to File's Owner
EDIT: Does the full error message give a clue? Why the NSApplication?
*** Illegal NSTableView data source (<NSApplication: 0x100607ad0>).
What am I missing? What should I check to resolve?
Image included to help visualize.
EDIT 2: (New info)
I deleted the data source & delegate connection from the table view and the error disappeared. The same IB designed window opens with an empty table view.
My 'project' is more complicated than the documentation covers. How to add a Window Controller to the Cocoa/Core Data template and utilize this controller is not easily found.
The most pronounced symptom was that the code in the intended controller was not being executed. The 2 required delegate methods were present. awakeFromNib wasn't being called either.
After more research, it appears the 'missing link' is the (previously deleted) NSObject set to the custom class of MainWindowViewController or MainWindowController in the nib file. I'm still looking for why this needs to be or why connecting to the File's Owner doesn't make the connection.
On the one hand, we can set the File's Owner to the custom class (MainWindow)ViewController or (Main)WindowController and connect the contained views to File's Owner. This doesn't work as I expected.
On the other hand, (apparently correct) we can add an NSObject to the MainMenu.xib file, set it's custom class to the (MainWindow)ViewController or (Main)WindowController and then connect outlets to the subviews to this object. The step of adding this object in IB is the only way I could find of connecting the window to the controller.
Ive recently started migrating a project to MagicalRecord and cant find how i would bind it to an NSArrayController in the interface builder of XCode 4.
The approach ive taken so far (besides lots of google) is making a reference to the [MagicalRecord defaultContext] and binding to that but i get an error: "Cannot perform operation without a managed object context"
Any pointers in the right direction would be really appreciated.
Make sure you turn on MagicalRecord as mentioned in the comment. You may also have to make a property in your app delegate that exposes the default managed object context provided by MagicalRecord:
- (NSManagedObjectContext *) applicationContext;
{
return [NSManagedObjectContext MR_defaultContext];
}
This is so that binding has something to hold onto...though I've not used it in that scenario myself. Let me know how it turns out.
Using this guide I have created a static library (let's call it AppCore) that can be shared between the Mac OS X and iOS versions of one app. This static library uses Core Data and the point of it is to share the model part and schema versioning between different implementations.
I created a NSPersistentDocument based project that will depend on this AppCore. In this project I added a reference to the .xcdatamodel file. Then I created a simple table view with add/remove buttons to edit an array of one entity type with the assisted "new core data entity" item. This created an instance of NSArrayController and the required bindings for the add/remove behaviour.
Now, everything seems to work fine when I'm using the default class for the Core Data entities (NSManagedObject) and I'm able to add new rows using the +/- buttons. However, when I change the entity implementation class to a custom one, I'm getting an error
Failed to create new object
This seems to come from the NSArrayController and it seems to be unable to instantiate the required entity. I can, however, create one in the NSPersistentDocument subclass by:
[NSEntityDescription insertNewObjectForEntityForName:#"SomeEntity" inManagedObjectContext:[self managedObjectContext]]
What confuses me is why the instance of NSArrayController can't. If I understand correctly, the array controller is instructed to create an entity, not class and my guess is that the entities are created with the help of NSEntityDescription class. I could implement my own version of the array controller's add: but then again, it might be that here something is fundamentally wrong. I haven't touched the init:s and the custom entity class implementation is simply for convenience, to access the attributes directly.
I have tried changing the base SDK on the AppCore but without effect. Currently it uses the iOS version but I'm not sure how it should be. This is another question but if unrelated, I might ask it here on a separate question.
So, to summarize, why can't the NSArrayController create an instance of this entity?
Thanks in advance.
Update
This works if I add the SomeEntity class from the AppCore to the dependent project as a reference. This is not the most usable way since modifications to the AppCore has to be propagated to the dependatnt projects also.
Bingo. I missed the "-ObjC" flag for the dependant project's "other linker flags". Now everything works like a charm.