Integrating the Omni frameworks into an app
The OmniGroup, makers of apps such as OmniGraffle, have released a lot of their code as the open source Omni Frameworks. This is great: there are things like a document picker with support for OmniPresence, a rich text editor, classes for zoomable tiled views, and many many other things too.
Unfortunately, the Omni Frameworks are barely documented. There is a sample app, called TextEditor, but despite the existence of this app it took me quite a while to work out how to get the frameworks to compile and to present a blank document picker on screen in a sample app. Here I’ll try to document some of what I did.
A quick disclaimer: I’m still learning about the Omni Frameworks. I don’t know if I’m doing things right or not, nor can I answer any of your questions. This isn’t meant to be a tutorial that tells you every step, so if it doesn’t work for you, you may have to do some investigation on your own.
One thing to note is that on iOS I prefer not to use Interface Builder, but rather to set everything up through code. Omni’s sample app uses IB, so that’s one difference I had to account for.
Setting things up
This was my first real foray into using Xcode 4’s Workspaces. I set things up this way because that’s how Omni’s sample project was set up. So start by making a workspace for your app, with your app’s project inside it.
I first cloned the git repository into a directory within my project directory. Then I added some of the Omni Frameworks projects as subprojects to my project:
As shown in that screenshot, I added OmniBase, OmniFoundation, OmniQuartz, OmniAppKit, OmniFileStore, OmniFileExchange, OmniUI, OmniUIDocument and OmniUnzip as subprojects of my project. I also added FixStringsFile as another project within the same workspace.
I also dragged all the Configurations files (the .xcconfig files, from in the Configurations directory within the OmniFrameworks root) into a new group in my app’s Xcode project.
I added the Omni libraries as target dependencies for my app’s target:
I added a new Run Shell Script build phase, to run Omni’s CopyLibraryResources script:
(note that the path to the script is the path from your Workspace file. I’ve put the OmniFrameworks in a folder called OmniGroup, which is why that is the first path component.)
I made sure to link my app with the Omni frameworks, and any frameworks they required:
I told Xcode to use the appropriate configuration files for the different targets and build types. This is also the first time I used configuration files.
Constructing the app
Now to put the app together. As I said, I dislike using nib files on iOS, so the first thing I did was to remove the project’s main interface filename:
Now to do enough to get a document picker on screen. (Note that we’re not going to make it do anything yet, we’re just going to make it appear.)
Make your app delegate class inherit from OUIDocumentAppController:
#import <UIKit/UIKit.h> #import <OmniUIDocument/OUIDocumentAppController.h> @interface AppDelegate : OUIDocumentAppController @property (strong, nonatomic) UIWindow *window; @end
Then, in AppDelegate.m, let’s get a window displaying with a document picker in it:
#import "AppDelegate.h" #import <OmniUIDocument/OUIDocument.h> #import <OmniUIDocument/OUIDocumentPicker.h> #import <OmniUIDocument/OUIDocumentPickerDelegate.h> #import <OmniUIDocument/OUIMainViewController.h> @interface AppDelegate () @end @implementation AppDelegate<OUIDocumentPickerDelegate> - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; [self.window makeKeyAndVisible]; self.documentPicker = [[OUIDocumentPicker alloc] init]; self.documentPicker.delegate = self; self.mainViewController = [[OUIMainViewController alloc] init]; self.window.rootViewController = self.mainViewController; return [super application:application didFinishLaunchingWithOptions:launchOptions]; } @end
Then build and run. You should get something like this:
That’s all for now. I haven’t explored how to use any of the Omni classes yet. I may post more once I do.