Cannot create NSArray from object - cocoa

XCode Error:
GNU gdb 6.3.50-20050815 (Apple version gdb-1708) (Mon Aug 8 20:32:45 UTC 2011)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin".tty /dev/ttys000
[Switching to process 2530 thread 0x0]
2011-11-12 18:29:29.857 RaiseMan[2530:707] Cannot create NSArray from object <Document: 0x100539a00> of class Document
2011-11-12 18:29:29.879 RaiseMan[2530:707] Cannot create NSArray from object <Document: 0x10015dda0> of class Document
2011-11-12 18:30:10.362 RaiseMan[2530:707] Cannot create NSArray from object <Document: 0x1001b0a90> of class Document
person.h:
#import <Foundation/Foundation.h>
#interface Person : NSObject
{
NSString *personName;
float expectedRaise;
}
#property (readwrite, copy) NSString *personName;
#property (readwrite) float expectedRaise;
#end
person.m:
#import "Person.h"
#implementation Person
- (id) init
{
self = [super init];
expectedRaise = 5.0;
personName = #"New Person";
return self;
}
- (void)dealloc
{
[personName release];
[super dealloc];
}
#synthesize personName;
#synthesize expectedRaise;
#end
document.h:
#import <Cocoa/Cocoa.h>
#interface Document : NSDocument
{
NSMutableArray *employees;
}
- (void)setEmployees:(NSMutableArray *)a;
#end
document.m
#import "Document.h"
#implementation Document
- (id)init
{
self = [super init];
//if (self) {
employees = [[NSMutableArray alloc] init];
//}
return self;
}
- (void)dealloc
{
[self setEmployees:nil];
[super dealloc];
}
-(void)setEmployees:(NSMutableArray *)a
{
//this is an unusual setter method we are goign to ad a lot of smarts in the next chapter
if (a == employees)
return;
[a retain];
[employees release];
employees = a;
}
- (NSString *)windowNibName
{
// Override returning the nib file name of the document
// If you need to use a subclass of NSWindowController or if your document supports multiple NSWindowControllers, you should remove this method and override -makeWindowControllers instead.
return #"Document";
}
- (void)windowControllerDidLoadNib:(NSWindowController *)aController
{
[super windowControllerDidLoadNib:aController];
// Add any code here that needs to be executed once the windowController has loaded the document's window.
}
- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError
{
/*
Insert code here to write your document to data of the specified type. If outError != NULL, ensure that you create and set an appropriate error when returning nil.
You can also choose to override -fileWrapperOfType:error:, -writeToURL:ofType:error:, or -writeToURL:ofType:forSaveOperation:originalContentsURL:error: instead.
*/
NSException *exception = [NSException exceptionWithName:#"UnimplementedMethod" reason:[NSString stringWithFormat:#"%# is unimplemented", NSStringFromSelector(_cmd)] userInfo:nil];
#throw exception;
return nil;
}
- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError
{
/*
Insert code here to read your document from the given data of the specified type. If outError != NULL, ensure that you create and set an appropriate error when returning NO.
You can also choose to override -readFromFileWrapper:ofType:error: or -readFromURL:ofType:error: instead.
If you override either of these, you should also override -isEntireFileLoaded to return NO if the contents are lazily loaded.
*/
NSException *exception = [NSException exceptionWithName:#"UnimplementedMethod" reason:[NSString stringWithFormat:#"%# is unimplemented", NSStringFromSelector(_cmd)] userInfo:nil];
#throw exception;
return YES;
}
+ (BOOL)autosavesInPlace
{
return YES;
}
#end
Full project code: http://sharesend.com/zyca7

I run into the same problem today and I have already solved it.
You should bind the column rather than the cell to the array controller.

Without downloading the zip file from ShareSend (please use a better host, such as Dropbox, or better yet, some form of version control), I can only guess that you have bound an array controller's contentArray to your document but failed to specify an array property of that document.
Telling the array controller to use the document itself as its content array will not work, because a document is not an array. Go into your nib, select the array controller, edit the contentArray binding, and specify the model key path for the array property you want to bind it to.

Related

Key value Observer is not getting called when there is a change in property in cocoa

I had 2 Objects Obj1 and Obj2. Where Obj1 is having a property isLocalChanges(BOOL) to check for any local changes made. I need to observe the change for this isLocalChanges if there is any changes I am setting the value to YES.
I written an observer for this property isLocalChanges in Obj2:
#interface Obj2 : NSObject
{
Obj1 *sampleObj;
}
#property (nonatomic,retain) Obj1 * sampleObj;
#end
#implementation Obj2
#synthesize sampleObj;
- (id)init
{
if (self = [super init])
{
sampleObj = [[Obj1 alloc] init];
[sampleObj addObserver:self
forKeyPath:#"isLocalChanges"
options:NSKeyValueObservingOptionNew
context:nil];
}
return self;
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:#"isLocalChanges"]) {
NSLog(#"isLocalChanges Observer");
if ([[change objectForKey:#"new"] boolValue]) {
NSLog("#\n Found Local Changes...");
}
}
}
}
Declaration and usage of isLocalChanges property that I used:
#interface Obj1 : NSObject
{
BOOL _isLocalChanges;
}
#property (assign) BOOL isLocalChanges;
#end
and in the Obj1.m
did #synthesize isLocalChanges = _isLocalChanges;
And Inside the below method I am setting the value for isLocalChanges property.
-(void) localChangesMade
{
self.isLocalChanges = YES;
}
The issue is even if isLocalChanges property changed in Obj1, The method observeValueForKeyPath: is not triggering. At this point I am helpless an unable to find what going wrong.
Can anyone suggest me to resolve this issue...
The object you are allocating is going out-of-scope and will be destroyed as soon as the method returns:
SomeObject *Obj2 = [[SomeObject alloc] init];
Make it an instance variable instead.
You are using the identifier Obj2 for three different things (a) as a class name (b) as an instance variable/property and (c) as a local variable. This is not good.
It is probably the third use which is your immediate problem, it is probably meant to be a use of (b). Instead of:
if (self = [super init])
{
SomeObject *Obj2 = [[SomeObject alloc] init];
you probably want:
if (self = [super init])
{
Obj2 = [[SomeObject alloc] init];
etc. The SomeObject *Obj2 local variable's lifetime is only the body of the if.
However that fix has you assigning an instance of type SomeObject to a property of type Obj1, so you may have a problem there as well.
Finally you never show the declaration or use of isLocalChanges, so there is no indication that you're actually assigning to this property using its setter - and if you're not then there won't be any KVO notifications.

Illegal DataSource, but everything is implemented fine

Getting :
*** Illegal NSTableView data source (<NSApplication: 0x101602bc0>). Must implement numberOfRowsInTableView: and tableView:objectValueForTableColumn:row:
Code .h
//
// AppDelegate.h
// MySQL
//
// Created by - on 10/12/12.
// Copyright (c) 2012 - Software. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#interface AppDelegate : NSObject <NSApplicationDelegate> {
NSMutableArray *tabelle_totali;
IBOutlet NSTableView *tabella_tabelle_totali;
IBOutlet NSTableView *tabella_contenitore;
}
#property (assign) IBOutlet NSWindow *window;
//Metodo per scaricare dati
- (void) download_tabelle ;
//Manipolazione tabelle ricevute
- (void)tabelle_ricevute:(NSData *)tabelle;
//Refresh tabella
- (IBAction)refresh_tablelle:(id)sender;
//Refresh tabelle
- (int)numberOfRowsInTableView:(NSTableView *)aTableView;
- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex;
#end
Code .m
//
// AppDelegate.m
// MySQL
//
// Created by - on 10/12/12.
// Copyright (c) 2012 Alberto Bellini Software. All rights reserved.
//
#import "AppDelegate.h"
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
[self download_tabelle];
[tabella_tabelle_totali reloadData];
}
- (void) download_tabelle {
NSMutableString *databaseURL = [[NSMutableString alloc] initWithString:#"http://*********************.php"];
//inizializzazione richiesta url
NSURL *url = [NSURL URLWithString:databaseURL];
//Richiesta asincrona per richiedere dati
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *tabelle, NSError *error)
{
[self tabelle_ricevute:tabelle];
}
];
}
- (void)tabelle_ricevute:(NSData *)tabelle
{
NSString *response = [[NSString alloc] initWithData:tabelle encoding:NSUTF8StringEncoding];
NSArray *tmpResp = [response componentsSeparatedByString:#"####"]; //This array splits the response string
NSLog(#"%#",response);
//Aggiungo le mie tabelle al mio array
[tabelle_totali addObjectsFromArray:tmpResp];
}
- (IBAction)refresh_tablelle:(id)sender {
//Cancello vecchi dati
while([[tabella_tabelle_totali tableColumns] count] > 0) {
[tabella_tabelle_totali removeTableColumn:[[tabella_tabelle_totali tableColumns] lastObject]];
}
NSTableColumn *column = [[NSTableColumn alloc] initWithIdentifier:#"1"];
[column setWidth:143];
[[column headerCell] setStringValue:#"*******"];
[tabella_tabelle_totali addTableColumn:column];
[tabella_tabelle_totali reloadData];
}
-(NSInteger)numberOfRowsInTableView:(NSTableView *)aTableView {
return 5;
}
-(id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row {
return #"hello world";
}
#end
Sorry lot of code is written in italian, but the issue is "international".. Why do i get this error ? The table dataSource is connected to the File's owner and the outlets as well..
When running the app instead of displaying 5 rows with 5 "hello world", obviously nothing happens.. Help
The problem may be in your xib file containing your table view. Have you set the table view's delegate to the File's Owner (which would be an instance of NSApplication), or have you set its delegate to your application delegate? It needs to be set to your application delegate.
If you haven't set up an object (visible in the margin to the left of your UI layout) representing your application delegate, you should do so, and connect your table view's delgate connection to that.
When using Swift, the issue may be that the data source class has not explicitly implemented the NSTableViewDataSource protocol. In particular, with the API renaming in Swift 3, it appears to be the protocol that causes the mapping of the Swift 3 syntax tableView(_:objectValueFor:row:) to the Objective-C selector tableView:objectValueForTableColumn:row:.
I discovered this when implementing a table view data source; although I had implemented the correct methods in Swift, I got the *** Illegal NSTableView data source message at runtime. I was confused until I realized I had forgotten to include the protocol conformance in my class declaration.

Zooming MkMapView from another class

I have a ViewController with UITableView *myTable and MKMapView *myMap designed in xib, but the table delegate/datasource and the map delegate are in another class, named SubClass. When I press a button in ViewController the SubClass parse in the tablecells latitude and longitude from a xml remote file, and now I want to zoom myMap into this coordinates every time I select the rows of myTable: Well, I can't find a way to call this zoom FROM SubClass. This is, simplified, my code:
ViewController.h
// ViewController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import "SubClass.h"
#interface ViewController : UIViewController {
IBOutlet UITableView *myTable;
IBOutlet MKMapView *myMap;
SubClass *subClassIstance;
}
- (void)buttonPressed:(id)sender
#property (nonatomic, retain) IBOutlet MKMapView *myMap;
ViewController.m
// in ViewController.m
- (void)buttonPressed:(id)sender {
subClassIstance = [[SubClass alloc] init];
myTable.delegate = SubClass;
myTable.dataSource = SubClass;
[myTable reloadData];
subClassIstance = [[SubClass alloc] loadMap:myMap];
}
SubClass.h
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface SubClass : NSObject <UITableViewDataSource, UITableViewDelegate, MKMapViewDelegate> {
}
- (void)loadValues;
- (id)loadMap:(MKMapView *)mapView;
- (id)zoomTheMap:(NSMutableString *)string1 :(NSMutableString *)string2 :(MKMapView *)mapView; // IS IT RIGHT???
SubClass.m
- (id)init{
self = [super init];
if ( self != nil ) {
[self loadValues];
}
return self;
}
- (void)loadValues {
// CODE TO PARSE VALUES OF LONGITUDE AND LATITUDE TO PASS IN THE TABLE CELLS
latitudeFromLoadValues = // NSMutableString parsed value from a xml remote file
longitudeFromLoadValues = // NSMutableStringparsed value from a xml remote file
}
- (id)loadMap:(MKMapView *)mapView
{
if (self) {
mapView.delegate = self; // CODE TO LOAD ANNOTATIONS AND OTHER STUFF. IT WORKS!
}
return self;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
latitudeFromLoadValues = [dataParsed objectAtIndex:indexPath.row];
longitudeFromLoadValues = [data2Parsed objectAtIndex:indexPath.row];
[self zoomTheMap:latitudeFromLoadValues :longitudefromLoadValues :???]; // IS IT CORRECT? WHAT IS THE RIGHT *MKMAPVIEW?
}
- (id)zoomTheMap:(NSMutableString *)string1 :(NSMutableString *)string2 :(MKMapView *)mapView {
NSLog(#"%#",string1);
NSLog(#"%#",string2);
MKCoordinateRegion region;
region.center.latitude = [string1 floatValue];
region.center.longitude = [string2 floatValue];
region.span.latitudeDelta = 2.0;
region.span.longitudeDelta = 2.0;
// I KNOW, I HAVE TO CALL myMap from ViewController! But with an istance?
mapView.delegate = self;
mapView.region = region;
return self;
}
Well, the rest of code works! I can see *myMap in ViewController loaded with some annotations declared in SubClass and *myTable loaded with cells populated with latitude and longitude parsed in SubClass; I can also see correct longitude and latitude passed in string1 and string2 but when I select the single table cell I don't see myMap zooming, I think I am using the wrong method. Can U help me, please?
loadMap shouldn't return self, only init methods should do that.
In buttonPressed you allocate a new SubClass, do some stuff to it, then allocate another SubClass and call its loadMap function. The last line should be [subClassIstance loadMap:myMap], but you'll also want to reconsider allocating a new SubClass every time that button is pressed.
I think you're really going about this the wrong way. Why do you need a SubClass (terrible name BTW, it says nothing about what it is for)? What class does it extend? If the ViewController has the MKMapView, it is usually the one to issue commands to the map. I can understand you having a separate datasoucre for the tableview, but not the rest. If you make the VC its own table and map delegate you'll simplify things a lot.
If you really want to have a subclass in your code then you should be calling loadMap on the instance you created on the first line of buttonPressed
- (void)buttonPressed:(id)sender {
subClassIstance = [[SubClass alloc] init];
myTable.delegate = SubClass;
myTable.dataSource = SubClass;
[myTable reloadData];
[subClassIstance loadMap:myMap];
}
and your loadMap would look like
- (void)loadMap:(MKMapView *)mapView
{
mapView.delegate = self;
}
However if that's all loadMap does you don't need a function for that, you could just make buttonPressed do it all.
- (void)buttonPressed:(id)sender {
subClassIstance = [[SubClass alloc] init];
myTable.delegate = SubClass;
myTable.dataSource = SubClass;
[myTable reloadData];
myMap.delegate = subClassIstance;
}
Example init function:
- (id)initiWithMapView: (MKMapView)* mapView
{
self = [super init];
if(self)
{
theMap = mapView;
theMap.delegate = self;
[self loadValues];
....
}
return self;
}
If you use this you won't have to set the map delegate or return self all the time and you can use theMap (as declared in your answer) in every function.
Well, I have found a simply solution, for those interested: first, I have defined a generic MKMapView *theMap in my SubClass.h, that now looks like:
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface SubClass : NSObject <UITableViewDataSource, UITableViewDelegate,
MKMapViewDelegate> {
MKMapView *theMap // NEW CODE!!!
}
- (void)loadValues;
- (id)loadMap:(MKMapView *)mapView;
- (id)zoomTheMap:(NSMutableString *)string1 :(NSMutableString *)string2 :(MKMapView *)mapView;
In loadMap method I have compared *theMap to mapView called by the SubClassIstance in VC (my *myMap that I want to zoom), so now we have:
- (id)loadMap:(MKMapView *)mapView
{
if (self) {
mapView.delegate = self;
theMap = mapView; // NEW CODE !!!
// CODE TO LOAD ANNOTATIONS AND OTHER STUFF. IT WORKS!
}
return self;
}
In didSelectRowAtIndexPath I have passed *theMap as mapView argument of zoomTheMap method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
latitudeFromLoadValues = [dataParsed objectAtIndex:indexPath.row];
longitudeFromLoadValues = [data2Parsed objectAtIndex:indexPath.row];
[self zoomTheMap:latitudeFromLoadValues :longitudefromLoadValues :theMap]; // NEW CODE !!!
}
The zoomTheMap method doesn't change, and now, "magically", every time I press a row of my table, the *myMap designed in the VC xib (but with delegate in SubClass) zooms into the coordinates stored in the cells:
- (id)zoomTheMap:(NSMutableString *)string1 :(NSMutableString *)string2 :(MKMapView *)mapView {
MKCoordinateRegion region;
region.center.latitude = [string1 floatValue];
region.center.longitude = [string2 floatValue];
region.span.latitudeDelta = 2.0;
region.span.longitudeDelta = 2.0;
mapView.delegate = self; // here mapView is *theMap passed in didSelectRowAtIndexPath, AKA original mapView istance used to delegate *myMap in VC
[mapView setRegion:region animated:YES];
return self;
}
Maybe its not an "elegant" way, but it now works! ;=)

NSMutableDictionary setObject:forKey - custom class

I am using this in a UINavigation environment.
I have customClassA. It inherits customClassB and one of its object is a NSMutableDictionary.
I alloc and init customClassA in a viewController, then for adding data, I am pushing a new viewController into the stack. The addNewDataViewController sends the newly added data, a customClassB object back by its delegate. Everything works fine so far.
customClassA has to store the returned object (customClassB) into its NSMutableDictionary object with a key (an NSString created from NSDate).
I get "mutating method sent to immutable object" error and can't think of any solution.
Any help is appreciated.
Thanks.
===========================
interface customClassA : NSObject
{
NSDate date;
NSArray *array; // will contain only NSString objects
}
// and the rest as customary
...
#import "customClassA.h"
interface customClassB : NSObject
{
NSString *title;
NSMutableDictionary *data; // will contain values of customClassA with keys of NSString
}
// and the rest as customary
...
#import "customClassB"
#interface firstViewController : UITableViewController <SecondViewControllerDelegate>
- (void)viewDidLoad
{
self.customClassB_Object = [customClassB alloc] init];
// and the rest...
}
- (void)secondViewControllerDidSaveData:(customClassA *)aData
{
[self.customClassB_Object.data setObject:aData forKey:[NSString stringWithFormat:#"%#", aData.date]];
// update tableView
}
Make sure you are initializing the NSMutableDictionary with something like
NSMutableDictionary *myDictionary = [[NSMutableDictionary alloc] init];
It would appear that your NSMutableDictionary is getting created with an NSDictionary instance instead of a NSMutableDictionary
Althoguh I added the following code to customClassB implementation, it still didn't work.
#implementation customClassB
- (id)init
{
self = [super init];
if (self)
self.data = [NSMutableDictionary alloc] init];
return self;
}
so I added two custom methods to my customClassB implementation, as well as in the header file:
- (void)appendData:(customClassA *)aData;
- (void)removeDataWithKey:(NSString *)aKey;
and instead of manipulating the data dicionary of customClassB in my viewController, I simply call that method and pass the data object to the class and it did the trick.

Problems creating a new Document-based Core Data project

I am trying to create a Core Data-based Mac OS X application. I've used Core Data on iOS, but things are a little different with AppKit. I am also using Xcode 4.1 on 10.7, and I know some Core Data things have changed on Lion. The only up-to-date reference from Apple is a recent WWDC session, which promises/suggests updated references on Apple.com, but most of the Core Data stuff is very out of date.
To start, I used Xcode to generate a Document-based project using Core Data. I hollowed out some of the Main Menu bits (deleted some menu items) and got rid of the NSWindow object inside Main Menu.xib, creating my own MyDocument.xib with a NSWindow (and sub-views) instead.
Questions:
I assume that a Persistent Store Controller always needs a persistent store, so if a new document is created, I'm just adding an in-memory store. When opening up from disk, I create it using the SQLite store. Is that correct?
I (ostensibly) do a store migration in writeToURL:ofType:error: if the url is different. But if I set a breakpoint in writeToURL:ofType:error:, and then hit Save, my breakpoint is not hit. Why not?
If I choose "Revert to Saved", the application crashes -- hard. I have to force-quit it (and quit Xcode). Why?
(Very) old video tutorials suggest a way to easily bind data to a UIView like a table. Following along with Xcode is impossible since so much has changed. Any newer references out there for that?
Code:
MyDocument.h:
#import <Cocoa/Cocoa.h>
#interface MyDocument : NSPersistentDocument
{
#private
NSManagedObjectModel* mom;
NSPersistentStoreCoordinator* psc;
NSManagedObjectContext* moc;
}
#end
MyDocument.m:
#import "MyDocument.h"
#interface MyDocument ()
- (void)setUpManagedObjectModel;
- (void)setUpPersistentStoreCoordinator;
- (void)setUpManagedObjectContext;
- (BOOL)addPersistentStore:(NSString*)type url:(NSURL*)url error:(NSError**)outError;
#end
#implementation MyDocument
- (void)dealloc
{
[moc release];
[psc release];
[mom release];
[super dealloc];
}
- (id)init
{
self = [super init];
if (self)
{
[self setUpManagedObjectModel];
[self setUpPersistentStoreCoordinator];
[self setUpManagedObjectContext];
}
return self;
}
- (id)initWithType:(NSString *)typeName error:(NSError **)outError
{
self = [super initWithType:typeName error:outError];
if (self)
{
[self addPersistentStore:NSInMemoryStoreType url:nil error:outError];
}
return self;
}
- (BOOL)readFromURL:(NSURL *)url ofType:(NSString *)typeName error:(NSError **)outError
{
return [self addPersistentStore:NSSQLiteStoreType url:url error:outError];
}
- (BOOL)writeToURL:(NSURL *)url ofType:(NSString *)typeName error:(NSError **)outError
{
NSPersistentStore* currentStore = [[psc persistentStores] lastObject];
if (![[currentStore URL] isEqual:url])
{
NSPersistentStore* newStore = [psc migratePersistentStore:currentStore
toURL:url
options:nil
withType:typeName
error:outError];
if (!newStore)
{
return NO;
}
}
return [moc save:outError];
}
- (NSString *)windowNibName
{
// Override returning the nib file name of the document
// If you need to use a subclass of NSWindowController or if your document supports multiple NSWindowControllers, you should remove this method and override -makeWindowControllers instead.
return #"MyDocument";
}
- (void)windowControllerDidLoadNib:(NSWindowController *)aController
{
[super windowControllerDidLoadNib:aController];
// Add any code here that needs to be executed once the windowController has loaded the document's window.
}
+ (BOOL)autosavesInPlace
{
return YES;
}
- (BOOL)validateMenuItem:(NSMenuItem *)item
{
NSLog(#"menu item: %#", [item title]);
return YES;
}
#pragma mark Private Methods
- (void)setUpManagedObjectModel
{
NSURL* modelUrl = [[NSBundle mainBundle] URLForResource:#"MyDatabase" withExtension:#"momd"];
mom = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelUrl];
}
- (void)setUpPersistentStoreCoordinator
{
psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom];
}
- (void)setUpManagedObjectContext
{
moc = [[NSManagedObjectContext alloc] init];
[moc setPersistentStoreCoordinator:psc];
}
- (BOOL)addPersistentStore:(NSString*)type url:(NSURL*)url error:(NSError**)outError
{
NSDictionary* options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
NSPersistentStore* ps = [psc addPersistentStoreWithType:type
configuration:nil
URL:url
options:options
error:outError];
return (ps != nil);
}
#end
If you're using NSPersistentDocument, by default all of this is handled for you, you don't need to do any Core Data setup. NSPersistentDocument will automatically handle creating, saving and migrating the persistent store.
If you want to control how the persistent store is configured, just override
-configurePersistentStoreCoordinatorForURL:ofType:modelConfiguration:storeOptions:error:
Then you can just ask the document for its managedObjectContext when you need it and code away.
I highly recommend you read Apple's NSPersistentDocument tutorial for more detail.

Resources