views:

1163

answers:

5

Hi everyone,

I am one of the great unwashed masses of .NET developers keen to try their hands at Mac OS X development. At the moment I am trying to figure out the various elements of Cocoa and getting a bit stuck on Core Data.

I noticed most of the documentation and resources available on the Web involve a broad end-to-end tutorial, beginning from models, generating classes, Document-based UI, etc. Not enough seem to be focused on each bit, or at least not enough examples.

Can someone please point me in the right direction, be it online material or books, that can give me detailed instruction of various bits? Maybe I'm stuck in the .NET world but I still think in terms of data access layer, etc. I'd like to know the basics of "CRUD", in setting up a persistent store, creating an entity, editing, saving to store, etc. Just the basics, without elaborating on the UI. It'd also be nice if I can unit test the various bits.

I guess I am trying to get into the correct mindset here - do any .NET devs out there know of appropriate reading material for people like us looking at Cocoa programming?

Many thanks, Dany.

+7  A: 

I would take the following route:

  1. Do the general Apple Cocoa tutorial: Currency Converter
  2. Next, dive into the Cocoa Bindings version of that tutorial (Bindings are very convenient and very important if you move on to Core Data)
  3. Cocoa Dev Central's "Build a Core Data App" tutorial

Further reading:
As always: the book Cocoa Programming for Mac OS X
Document-Based Application Architecture (ADC)
And finally: A comparison between some aspects of Cocoa and .net

weichsel
Absolutely not.Like Core Data, Cocoa bindings is not an entry-level technology. You should take a much longer route between starting with Cocoa and using either bindings or Core Data. And you should certainly not combine Core Data and Cocoa bindings until you have a solid grasp of each.
mmalc
+1  A: 

For the nuts-and-bolts though, you might find Apple's Core Data Basics useful - there's also a tutorial for building a GUI-less utility there.

rdocking
+9  A: 

First, as Apple's documentation (and recurring comments from Apple engineers) state, Core Data is an "advanced" Cocoa technology. Grokking Core Data requires knowledge of a lot of Cocoa paradigms and patterns. Seriously, learn Cocoa first. Then write a project (or several) without Core Data. Then learn Core Data. Seriously.

To quiet your curiosity, I'll take a stab at the CRUD answer, though it's not going to be the answer you want. The answer is that there is no CRUD pattern for Core Data, at least not the way you think of it. The reason is that Core Data is not a data access layer. It is an object graph management framework. That means the explicit, intended job of Core Data is to manage a graph of object instances. This graph has constraints (such as cardinality of relationships or constraints on individual instance attributes) and rules for cascading changes (such as a delete) through the graph. Core Data manages these constraints. Because an object graph may be too large to be stored in memory, Core Data provides an interface to your object graph that simulates[1] an entire object graph in memory via faulting (object instances are not "faults" when first brought into a managed object context and are "fired" to populate their attributes from the persistent store lazily) and uniquing (only one in-memory instance of a particular entity instance (in the persistent store) is created in the context).

Core Data just happens to use an on-disk persistent store to implement the interface of a large object graph. In the case of an SQLite persistent store, this implementation just happens to use a SQL-compatible database. This is an implementation detail, however. You can, for example create an in-memory persistent store that does not persist anything to disk but allows Core Data to manage your object graph as usual. Thus, Core Data is not really a data access layer. To think of it in these terms will miss it's true power and will lead to frustration. You can't use Core Data with an arbitrary data base schema (this is why all Core Data tutorials start with creating the NSManagedObjectModel). You shouldn't use Core Data as a persistence framework and use a separate model layer; you should use Core Data as a model layer and take advantage of Core Data's ability to persist the model's object graph to disk for you.

That said, to create an NSManagedObjectContext (which provides the object graph interface I described above):

NSManagedObjectModel *mom = [NSManagedObjectModel mergedModelFromBundles:[NSArray arrayWithObject:[NSBundle mainBundle]]]; // though you can create a model on the fly (i.e. in code)
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:mom];

NSError *err;

// add an in-memory store. At least one persistent store is required
if([psc addPersistentStoreWithType:NSInMemoryPersistentStore configuration:nil URL:nil options:nil error:&err] == nil) {
  NSLog(@"%@",err);
}

NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] init];
[moc setPersistentStoreCoordinator:psc];

(note that I'm assuming you're using Garbage Collection; this code leaks in a manual memory management environment).

To add an entity instance (continuting with moc from above):

NSEntityDescription *entity = [NSEntityDescription entityForName:@"MyEntity" inManagedObjectContext:moc];  
//entity will be nil if MyEntity doesn't exist in moc.persistentStoreCoordinator.managedObjectModel

NSManagedObject *obj = [[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:moc];

Notice that you need an entity description to create a managed object (why tutorials start with the model) and that you can't create a managed object without a managed object context.

To update an entity instance:

[obj setValue:myValue forKey:@"attributeKey"]; //or use any method on `obj` that updates its state
NSError *err;
if(![moc save:&err]) {
  NSLog(@"%@", err); // an erro occurred in saving, perhaps due to optimistic locking failure
}

To delete an entity instance:

[moc deleteObject:obj];
if(![moc save:&err]) {
  NSLog(@"%@", err); // an erro occurred in saving, perhaps due to optimistic locking failure
}

[1]: For binary or XML persistent stores, the entire graph is stored in memory

Barry Wark
Thanks Barry - that's a fantastically detailed response. Thank you again for taking the time. Now I understand my misconception in thinking Core Data is a "DAL" as such. Having said that it begs the question - "How does one go about building any data-intensive/driven application?" I don't really mind if it's a domain-driven or ERD-driven development, either way is fine, but eventually I will need to persist a considerable amount of data in a database (preferably MySQL since it's similar to the SQL Server I'm used to).What are the best practices in creating such apps in the Cocoa world?
DanyW
BTW, I'm just trying to get a general wider view so I can potentially figure out what path I want to take. Thanks...
DanyW
Wow, that opens a whole big can of worms. I'll try to put your options in a second answer.
Barry Wark
+3  A: 

Doesn't look like anyone's mentioned these books yet:

  • Core Data by Marcus Zarra, The Pragmatic Programmers
  • Core Data for iPhone by Tim Isted, by Addison-Wesley (which, yes, is an iPhone book, but most of the principles of Core Data are shared across platforms)
Sixten Otto
+4  A: 

Core Data really isn't a data access layer (see my other answer for more). But what if you want a data access layer for Cocoa? What are your options? I'm a professional Cocoa and Qt developer and so far I've managed to avoid the Windows or Java enterprise world, so my evaluation of the options may not match yours exactly. Coming from an enterprise-y ecosystem, I expect you'll find the options a little scary. I've ordered them in what I expect will be most to least scary for you (roughly most to least Cocoa-y and so also roughly most to least familiar for me). Find the spot on the list where your stomach stops lurching and you've found your solution...

  1. Although Core Data is a very powerful framework for managing the object graph of the model component of an MVC architecture, you're not obligated to use it. You can write your own model layer and still play in the Cocoa MVC world. This is how we did it before Core Data. You can still use the Cocoa NSObjectController, NSArrayController, and NSTreeController if you want. Thus, you can roll your own data access layer using the native C/C++ APIs of your data base vendor.

  2. The BaseTen framework is a commercial licensed Core Data-like API on top of a PostgreSQL backend. It is really more of an ORM than an object graph management framework like Core Data, but the API is similar. My understanding is that it can handle existing (arbitrary) schema or make use of Core Data managed object models. They provide their own NSArrayController subclass that you can use as a drop in replacement for Cocoa's array controller. I've never used BaseTen personally, so I can't speak to its utility, but I've heard good things. As far as I know it's PostgreSQL only.

  3. The Python-Objective-C bridge, called PyObjC, is quite mature and ships with OS X since 10.5. Using this bridge you can write complete Cocoa apps in Python or write a hybrid Python/Objective-C app. Using PyObjC, you could make use of any of the Python ORMs such as SQLAlchemy to implement your model layer. Again, not no work but perhaps still relatively easy for a competent Python and Cocoa programmer.

  4. Apple's Enterprise Object Framework, part of WebObjects, is now a Java ORM that has an Objective-C ORM in its lineage. You can, I believe, still write desktop apps using WebObjects. I understand that many Cocoa patterns carry over, but this is a very different beast. I've never written WebObjects code, so I can't give you much more advice on this one.

  5. You can make use of a cross-platform toolkit. Qt can produce decent looking Mac UIs (though see below). Qt also has a model-layer framework that includes SQL support for several data bases in the QtSql module. Qt is not Cocoa at all. Savy Mac users don't like non-native apps. Qt is about as good as it gets for cross-platform on OS X, but it's not perfect. If you can stay native, do it.

  6. Any Java Swing/SWT crap. Again, this is powerful stuff, but it looks like hell on the Mac and users don't like it.

  7. Mono on OS X is relatively immature and I don't know what the status of any of the .Net ORMs are on Mono. It's something to take a look at though. As far as UI, the Mono-GTK stuff looks pretty bad on OS X. There is a C# binding for Qt called Qyoto which runs on Mono.

Barry Wark
You're right about one thing - it sure did scare me somewhat! I guess I've been somewhat brainwashed in the enterprise world - perhaps I should just take a few chill pills and calmly evaluate what I have to work with. I took another advice from here and bought the "Cocoa Programming for Mac OS X" book - time to be a true noob and learn everything properly - been a while since I've had to do that :o)Thanks.
DanyW