A few days ago I spent a lot of time tracking down a data validation error in Core Data which turned out to have a very simple cause.
The application I’m working on has two entities for customer and order. Each order must be linked to a single customer.
The first time I created a new order, I was able to save it successfully. The next time I tried to save an order, I got a validation error. When I inspect the new order I just created, it looks correct, with a proper customer relationship.
Looking at the NSManagedObjectContext in the debugger offers a few clues. You’ll see that it has sets of inserted & changed items, which you can inspect by typing ‘po managedObjectContext->_insertedObjects‘ or ‘po managedObjectContext->_changedObjects‘.
The set of inserted object contained exactly what I expected, but the set of changed items contained some unexpected items, including the previous order, which now had its customer relationship set to nil. Since the customer is required, the data validation failure was not on our newly inserted item, but on the previous order which used to be valid.
How could I be changing that previous order? I couldn’t find any place in my code which could have been doing it. Instead it turned out to be a simple error in my data model.
When you create a relationship, it can be either required or optional, and it can be to a single entity or to many entities. Every relationship also needs to have an inverse relationship.
In this case, my order had a required to-one relationship with a customer, which meant customer also had to have an inverse relationship to orders, which was optional. However, I neglected to set my customer to order relationship as to-many.
Therefore, although I never touched the customer’s relationship to orders, when I created a new order & set the customer, Core Data also set the customer’s order relationship. Since I didn’t make it to-many, doing so wiped out the relationship to the previous order, which also wiped out that order’s required relationship to a customer.
Moral of this story: check your relationships carefully and make sure you set the proper attributes for the inverse relationship. In this case, I spent many hours debugging something caused by setting a checkbox incorrectly in the model editor.
I’ve had a few questions about how to implement Twitter & FaceBook sharing, so here’s how I did it.
ShareKit provides an easy drop-in solution for posting to Twitter, FaceBook, Instapaper, Tumbler, and many other services. However, in many cases you don’t need all of the features and simply want to post a status to FaceBook or Twitter.
Call the shareItem: method of the appropriate subclass.
When you call shareItem: it will display the login & authentication prompt and show the item to be shared.
The most difficult part is setting up your application on Twitter or FaceBook with the correct permissions and obtaining the proper API keys. Read the instructions in SHKConfig.h carefully for details on how to set up your application and enter the API keys there.
I have my own branch of ShareKit at https://github.com/mike3k/ShareKit which fixes a problem related to iOS 5 and gets rid of most of the compiler warnings.
For my current project, I had to implement interprocess communication between a background process and an application. In the past, I would probably use AppleEvents or even CFMessage, but this tech note advises against using those techniques.
After some investigation, I found that Distributed Objects is the easiest & cleanest way to do it.
Distributed Objects works its magic with a set of proxy classes that pose as the actual object which exists in the other application. Here’s how to use it.
On the server side, you create a connection and vend that object using NSConnection’s setRootObject: method.
In the client application, you create a remote connection and ask for a proxy object. You then use that proxy object as if it was the actual object.
What really happens when you call the method in the client is that it gets packaged as a NSInvocation, which gets sent over the connection and is executed by the server process.