Sunday, June 17, 2012

Core Data Editor + Sandboxing = trouble

I just realized that the current Mac sandboxing situation makes a new major version of Core Data Editor impossible/not practical. A few weeks ago I published a blog post which describes an issue related to Core Data and sandboxing. Let me sum this post up really quickly: If you have a SQLite store it creates a temporary file during the save operation in order to be able to roll back in case something goes wrong.  The sandbox mechanism cannot handle this at the moment and therefor the save operation fails. Basically there are two workarounds (as described in the linked blog post):

  1. disable the creation of the journal file - this has bad side effects
  2. wrap the SQLite store file in a folder
Core Data Editor is a tool for developers which allows them to inspect and edit the data in a store file so the workarounds are not possible. The first workaround is not possible because it would lead to inconsistent data and Core Data Editor would be hold responsible for this. Workaround number two is a good workaround for 99% of the developers but I am in the situation that I cannot do this because Core Data Editor is a generic application. You should be able to throw anything at it - not only SQLite files wrapped inside a folder. Core Data Editor is not the only application having this problem. Basically any SQLite editor out there has this problem. One prominent example is Base from Menial - a competitor of Core Data Editor when it comes to editing Core Data SQLite stores.

The problem is more widespread

In my opinion the problem is even more widespread: Every application that can edit files through a library that has to generate temporary files in locations not supported by the sandbox mechanism is out of luck. I really hope that Apple is considering this Core Data issue something they have to fix. But how do we expect them to fix this? The journal file causing the problem is not created by Apple directly. The underlying SQLite library used by Core Data is creating the temporary file. Do we want Apple to go through every third party library and adjust the sandboxing mechanism according to the implementation details of these libraries? I guess not but in my opinion the problem described above is special. Core Data is an integral part of Cocoa and Cocoa Touch. It is an awesome framework. I fell in love with Core Data when it first came out with 10.4 (Tiger). Hell - I am even writing a whole book about Core Data. It is heavily pushed by Apple. Core Data is supposed to make iCloud a piece of cake for developers. Apple - please make an exception so that Core Data Editor can receive major updates and to make life easier for the other developers not using bundle-based file formats.

Monday, May 28, 2012

Core Data, Document-Based Application and Sandboxing

Every now and then one of my customers using Core Data Editor sends me a Core Data related question via e-mail. The last Core Data related question I got went like this:

I have a Core Data Document-Based application that is using the SQLite store. When I activate sandboxing I am not able to save the context anymore. Why is that and how can I work around this problem?
This question really caught my interest. Here is what I found out:

The save fails because the underlying SQLite library created temporary files on behalf of Core Data. You may have seen a file like this. Usually this file has the suffix "-journal". When you activate sandboxing your application is only are allowed to read and write to the store file itself and not to the "-journal" file. This explains why the save of the context fails. Until Apple has fixed this you can work around this by deactivating the creation of journal files. You can do this by sending the following pragma statement to the SQLite database:

pragma journal_mode OFF
or
pragma journal_mode MEMORY


Let me explain:
The first pragma statement completely disables the journaling of SQLite. You usually don't want to do this because you can't do a rollback anymore. The second pragma statement has less dramatic side effects: You can still rollback but the bookkeeping is done in memory. If your transactions are small this won't be a problem but you should be aware of the side effects.
Now that we know that its time to think about Core Data again. Core Data does not expose the SQLite database handle to the developer - with good reasons. Nevertheless there is a way that allows us to send the pragma statement to the SQLite database used by the SQLite store. When you add a persistent store to a coordinator you can specify an options dictionary. There is a key called NSSQLitePragmasOption that lets you specify another dictionary that contains the pragma statements you want to be executed by the SQLite store. I have described the procedure on Stackoverflow.com. Here is the code snippet that sets the journal mode to MEMORY:


NSDictionary *pragmaOptions = [NSDictionary dictionaryWithObject:@"MEMORY" 
                                                          forKey:@"journal_mode"];


NSDictionary *storeOptions = [NSDictionary dictionaryWithObject:pragmaOptions 
                                                         forKey:NSSQLitePragmasOption];


NSPersistentStore *store;
NSError *error = nil;
store = [psc addPersistentStoreWithType:NSSQLiteStoreType
                          configuration: nil
                                    URL:url
                                options:storeOptions
                                  error:&error];   

The last step is to bring it all together. In your NSPersistentDocument subclass you have to override the method that sets up the coordinator like this:

- (BOOL)configurePersistentStoreCoordinatorForURL:(NSURL *)url ofType:(NSString *)fileType modelConfiguration:(NSString *)configuration storeOptions:(NSDictionary *)storeOptions error:(NSError **)error {
   
   NSDictionary *pragmaOptions = [NSDictionary dictionaryWithObject:@"MEMORY" 
                                                             forKey:@"journal_mode"];
   
   NSDictionary *options = [NSDictionary dictionaryWithObject:pragmaOptions 
                                                        forKey:NSSQLitePragmasOption];
   
   return [super configurePersistentStoreCoordinatorForURL:url ofType:fileType modelConfiguration:configuration storeOptions:options error:error];
}


A more "secure" solution is to create a package and put in your store file there. This requires no pragma-voodoo. You can find a discussion about this topic in the developer forums. (Account required)

If you have found a better solution please send me an e-mail.



Flashcards Pro for iPad released

It was a long journey but I am pleased to announce that Flashcards Pro for iPad is now available in the App Store. Flashcards Pro is beautiful and easy to use application, that helps you learn new things quickly and efficiently. Here is a short video I made that should give you a good impression:



Over the next several months the iPad application will become a universal application that also runs on your iPhone and iPod Touch. The Mac application will also get a major update. The plan is to enable iCloud as soon the Mac application has been updated or the iPad app became universal. If you have feedback please send it directly to me via email.

Saturday, April 21, 2012

Flashcards for iPad: Status

Flashcards for iPad is doing well. The beta test has started approximately one week ago. Flashcards for iPad is more or less feature complete and with the help of the beta testers I am able to work out the rough edges. Once Flashcards for iPad has been released I will work on a major new version of Flashcards for Mac in order to enable iCloud syncing.



Thursday, April 12, 2012

Creating an iOS based Core Data Editor project (Video Tutorial)

I got it. The setup of an iOS project in Core Data Editor is not obvious. I promise to make it easier is one of the next releases of Core Data Editor. But until the improvements are released I don't want to leave you alone. This is why I made a short video tutorial that shows how to create an iOS project in Core Data Editor. So here it is:



I will release more video tutorials of this kind so if you want to know something particular let me know.

Tuesday, April 10, 2012

Objective-C needs Java's Annotations

TL;DR: Java's annotations feature allow a developer to annotate code. These annotations can be used either at run-time or compile-time to do awesome stuff. Objective-C needs this as well so that we can let mogenerator and other cool tools do its work more efficiently.

I am addicted to Objective-C. In my opinion Objective-C is a very nice and pragmatic language with a neat syntax and I have used it a lot during the last eight years. Lately I had to use Java a little bit. It was fun but I still like Objective-C more – although there is one thing about Java that I fell in love with and would like to see in Objective-C as well: Annotations.
First I will try to explain what Java annotations are and then I will describe which problems could be solved by having something like Java's annotations available in Objective-C.

Java Annotations

Java annotations allow a developer to add metadata to the code (e.g. to classes, methods, fields or packages). Every annotation has a name and the actual metadata in the form of key-value pairs. An annotation can be processed either at run-time (by using Java's reflection capabilities) or at compile-time (by providing a compiler plug-in – a so called annotation processor)). When an annotation is being processed a developer can do all sorts of things like executing existing code (at run-time) or by creating new code (at compile-time).

Annotations could be useful in Objective-C as well

Now it's time to talk about how annotations could be used to solve Objective-C related problems.


Eliminate the need to write boilerplate code
Writing code makes fun as long the code is not trivial. When working with Core Data (an object graph management framework used to persist data) a developer usually has to write a lot of boilerplate code. This (boilerplate) code is used to avoid compiler warnings, improve the performance, make your application code more read/writable and make it easier to debug. So usually a developer wants to have the benefits of the boilerplate code without writing it. This is why there are tools like mogenerator which generate the boilerplate code automatically. This is cool but manually generated code is a bad practice when developing an application: You have to manually regenerate the code when the model changes and new team members have to get familiar with the generator. It would be ideal to let the compiler generate the code that is usually generated by mogenerator. This would be possible if we had annotations. An annotation processor is basically a compiler plugin that can generate code, as already mentioned. You still get all the benefits of manually generated code (code competition, higher performance, ...) but without the drawbacks.

Remark: Core Data can also be used without the generated or handwritten boilerplate code. The framework generates the code at runtime but in order to avoid compiler warnings one usually writes/generates the code.

Typos are found by the compiler
Java has a few built in annotations. One annotation I found quite useful is the @Override annotation. You attach it to a method you intent to override. Why is this useful? Imagine you have a typo in the name of the method you intent to override: Your implementation never would get called. This is a problem that is also acknowledge by Apple in the form of a technical Q&A: "Common mistakes with delegation in Cocoa":
Capitalization errors are often the hardest to catch. Any of the methods of the NSTableDataSource informal protocol are likely candidates for subtle miscapitalization. For example, numberOfRowsInTableView: is often mistakenly entered as numberOfRowsInTableview:.
Apple goes even further and suggest to copy & paste code in order to prevent these errors:
Perhaps the safest habit to develop is to simply always cut and paste the method selector.
Wait. Using copy and paste to prevent errors in code? Questionable… That's where a @Override-annoation would come into play. The annotation could check at compile time if one is actually overriding a method or not. My friend Stefan Reuter told me about another benefit of @Override: Imagine a developer is overriding a method of a class provided by a third party. A few months later the third party decides to remove this method. If the developer annotated the method with @Override then the compiler will complain about a method that is overridden but which is no longer present. Sweet isn't it?

Remark: I think that in the case of Objective-C protocols we already have something similar. Starting with Objective-C 2.0 a message defines in a @protocol definition can be marked as required (@required) or as optional (@optional). If a class declares that it conforms to a protocol the developer is warned if the class does not respond to the messages marked as required.

We already have annotations!

Objective-C already had an "annotation-like" feature: properties:
@property (key1=value1, key2=value2, ...) Class *name;
With @property we tell the compiler how @synthesize generates code. So what I want to see in Objective-C is a generalized way to do the same thing @property/@synthesize does.

Tuesday, April 3, 2012

Core Data Editor 4.2

I am pleased to announce the release of Core Data Editor 4.2 - finally after a three month long journey of submitting, rejection, re-submitting, … (you get the idea). So what is new with 4.2?

Shortcuts

I have improved the most important shortcuts:
  • Create a managed object by pressing ⌘N
  • Create a new project by pressing ⌘⇧N
  • Reload the store file by pressing ⌘R
  • Delete a managed object by pressing ⌫
So creating a new project in Core Data Editor has the exact same shortcut than in Xcode.

Entities Table View

Some of you have very long entity names. Now you can make the entities table view wider than before. Have a look: Big Table

Bugfixes

In addition I have also fixed two annoying bugs:
  • Date attribute text field now responds to the tab key.
  • Refreshing the editor view (by clicking on the refresh button in the lower left corner) is much more stable.
Thank you all for your patience and stay tuned for the next release of Core Data Editor which will actually bring new features and more bug fixes. And a special thanks goes to everyone who reported bugs and provided freed back.

Happy Coding.



Friday, March 2, 2012

Automatically dismiss "App X Would like to Use Your Current Location" dialogs - easy?

tl;dr: Can a alert view shown by the framework (Core Location, …) automatically be dismissed by sending the appropriate touch events to the "OK"-button? Answer: No, not so easy. Want to know why? Read the whole thing.

Every iPhone user out there has probably seen the dialog below (in one way or the other):
Screen Shot 2012 03 02 at 1 28 18 PM
If an app wants to use the current location of an iPhone it has to get the users permission first. This is enforced by a so called "alert view" that is shown automatically by the framework once you (as a developer) try to use Core Location to get the current location of an iPhone. The alert view shown above has two options: "OK" which allows the app to use the current location and "Don't Allow" which is the opposite.
I always wondered if it is possible to automatically dismiss an alert view like this by simulating a click on the "OK"-button. It should be pretty straight forward because a alert view is an instance of UIAlertView which inherits from UIView. What a developer could do, once a alert view like this is shown by the framework automatically is this:
  • find the root view of the app
  • go through the whole view hierarchy recursively and try to find the instance of UIAlertView
  • suppose the "OK"-button on the UIAlertView is just another UIView (or UIButton) then it has to respond to touch events (UITouch, UIEvent)
  • create a "touch up inside" event and send it to the "OK"-button
  • the alert view should be dismissed and your app could use the current location without the users consent
A few days ago I tried to find out if it is really that easy. To make it short: It is not that easy.

Here is why

I believe that the alert view is contained in another process and so there is no way I know of that lets you access the view hierarchy of another process since they don't share the same address space.

How?

I wrote a sample application that registers an object as an observer at the default notification center. As name and object parameter I simply pass nil which means that my notification handler wants to receive every notification of the default notification center no matter who sent the notification and no matter how the notification is called:

[[NSNotificationCenter defaultCenter] addObserverForName:nil 
                                                  object:nil
                                                   queue:nil
                                              usingBlock:^(NSNotification *note) {
     NSLog(@"%@", note.name);
}];


The sample app then tries to access the current location and as soon the alert view pops up the sample app receives a notification saying that it will resign the active state. This does not proof that the alert view is shown by another process because an application usually resigns the active state because of two reasons:
An application is active when it is receiving events. An active application can be said to have focus. It gains focus after being launched, loses focus when an overlay window pops up or when the device is locked, and gains focus when the device is unlocked. ( found in the documentation about UIApplication)
So I turned on Instruments and made a few heapshots and analyzed the stack trace. Lets have a look:
Screen Shot 2012 03 02 at 2 37 25 PM
The -[SISViewController start:] method is the one requesting the current location. Then you see a few CL-calls and then three XPC function calls. XPC is Apples new inter process communication library. So clearly there is some kind of inter process communication going on. This may be the communication with the Core Location Deamon. More importantly I haven't seen a hint in the stacktraces that suggest that a overlay window or a view is created in the address space of the app.
To be clear: I have not found any evidence that suggests that the alert view is in the address space of another process either. Never the less what I found lets me believe exactly that and I think this would be a wise decision. I will try to find absolute proof by using more sophisticated reverse engineering techniques and then I will report back.