Skip to content
derpoliuk edited this page Sep 30, 2014 · 36 revisions

With the advent of sandboxing and XPC services in OS X 10.7 and the enforcement of sandboxing in the Mac App Store the iMedia framework had to adapt to an even broader spectrum of deployment scenarios. These are systematically addressed in iMedia 3.

Supported Environments

OS X: iMedia 3 is compatible with 10.6.8 and 10.7.3 and up. On 10.6 iMedia will always run non-sandboxed and without utilizing XPC services.

Xcode: Though not mandatory this guide assumes that your app is wrapped into an Xcode workspace. If it isn't yet you may want to consider doing it now (more on workspaces).

Since IMedia 3 no longer consequently implements forward method prototypes you must use llvm version 3.1 or higher. Thus, you should be fine with Xcode 4.3 and up (see also Objective-C Feature Availability Index).

Choose your Scenario

iMedia 3 can adapt to your app's deployment needs along the following dimensions (choose any combination):

  1. Sandboxed (in terms of OS X) / non-sandboxed
  2. With / without utilizing XPC services

Note regarding XPC services: When deployed XPC services serve the purpose of media fetching in respect to library types supported by iMedia (e.g. iPhoto or Lightroom libraries)

Let's start with the easiest scenario:

Scenario 1: Non-sandboxed and without utilizing XPC services

This is straight forward.

  1. Add iMedia as a submodule to your app:

     $ git submodule add https://github.com/iMediaSandboxing/iMedia.git Frameworks/iMedia
    

    Or, if you don't use git as your app's versioning tool simply clone iMedia:

     $ git clone https://github.com/iMediaSandboxing/iMedia.git
    

    and move the framework to your project folder.

  2. iMedia 3 depends on other (GitHub hosted) frameworks that are hooked to its repository via the git submodule command. These frameworks are (as of iMedia 3.0)

    • ObjectiveFlickr
    • XPCKit

    To clone these submodules to your local system in their correct (iMedia compatible) version you must execute the following git commands from the root directory of your local iMedia git repo:

     $ git submodule init
     <some response from git>
     $ git submodule update
     <some response from git>
    
  3. Add the iMedia.xcodeproj project file to your workspace or add it as a sub-project to your app (by dragging it into the navigator pane of Xcode)

  4. Open the iMedia project in your app's workspace and locate Products > iMedia.framework

  5. (This step only if you added iMedia as sub-project) Drag & Drop iMedia.framework to Build Phases > Target Dependencies

  6. Drag & Drop iMedia.framework to Build Phases > Link Binaries With Libraries

  7. Drag & Drop iMedia.framework to Build Phases > Copy Frameworks

  8. Repeat steps 3,4,5 and 7 to the ObjectiveFlickr framework located in the root directory of the iMedia repository

  9. You do not have to repeat steps 3,4,5 and 7 for the XPCKit framework since it is not utilized in this scenario

  10. Tell your app where to find the iMedia framework: Your application binary and (principally) all XPC services associated with the iMedia framework will link with the iMedia framework located in the application's bundle. Since the (relative) path from the location of these binaries to the location of the app-embedded iMedia framework is (naturally) different, iMedia uses the @rpath variable to tell the loader where to find it (see also Linking and Install Names by Mike Ash). To set the @rpath variable you must set the Runpath Search Paths build setting to @loader_path/../Frameworks for the target that builds your app's main binary.

Scenario 2: Sandboxed and without utilizing XPC services

If you are not yet familiar with app sandboxing on OS X you will like to first read Apple's App Sandboxing Design Guide.

  1. Apply steps 1-10 as described in scenario 1
  2. Select your application target and under Summary > Entitlements switch on Use Entitlements File and Enable App Sandboxing
  3. Add the following entitlements to your app's entitlement file:
    1. com.apple.security.files.user-selected.read-write YES will enable the user to grant entitlements to directories where necessary when prompted (e.g. library sits on external volume)
    2. com.apple.security.files.bookmarks.app-scope YES will ensure that entitlements granted by the user will persist across sessions or even reboot of the system. This one is also mandatory if your app likes to save image URLs obtained from iMedia.
    3. com.apple.security.temporary-exception.shared-preference.read-only com.apple.iApps will enable iMedia to locate Aperture and iPhoto libraries (note that this entitlement must be set up as a one-element array)
    4. com.apple.security.temporary-exception.shared-preference.read-only com.adobe.Lightroom, com.adobe.Lightroom2,... will enable iMedia to locate Lightroom libraries of their respective version (note that you have to append those entitlements to the entitlement of step 3.3 if you applied step 3.3. Add one entry for each major Lightroom version you want to qualify)
    5. Add access to the resources your app needs. E.g. to use images, you like to at least have Read Access to the user's Pictures folder (you may set this on the summary page of your application target)

Scenario 3: Non-sandboxed and utilizing XPC services

Regardless of whether your app runs sandboxed or not the iMedia rule for XPC services is:

If you deploy an iMedia XPC service to your app's bundle it will be utilized. If you don't, GCD will stand in instead.

Thus, to implement scenario 3 apply the following steps:

  1. Apply steps 1-10 as described in scenario 1

  2. Apply steps 3,4,5 and 7 of scenario 1 to the XPCKit framework located in the root directory of the iMedia repository

  3. Add a new Copy Files build phase and name it Copy XPC Services. Set Destination of this build phase to Wrapper and Subpath to Contents/XPCServices

  4. Open the iMedia project in your app's workspace and locate Products > iMedia.framework

  5. Make sure that all listed XPC services are already built (by explicitly building their targets)

  6. Drag all XPC services of library types your app supports and the FSEvents service to the newly created Copy XPC Services build phase (NOTE: if these XPC services have not been built Xcode will not be able to identify their locations and issue errors when trying to copy them).

    Technically you could just bundle some XPC services with your app and let other library types be handled by GCD – it will work. But it probably wouldn't be a consistent approach.

Scenario 4: Sandboxed and utilizing XPC services

  1. Apply steps 1-3 as described in scenario 2 but omit steps 3.2 - 3.4 (they won't harm execution of your app but Apple might not like superfluous entitlements on Mac App Store review). These entitlements are already granted to iMedia's XPC services where needed.
  2. Apply steps 2-6 as described in scenario 3

Host App Configuration

The test app provided with the repo (target iMediaTester) exercises a wealth of configuration options for the framework. Have a look at IMBTestAppDelegate.

Facebook Access Configuration

To take advantage of Facebook photo album integration you must provide a Facebook registered app id. You must create one here.

This Facebook app id must be provided by your delegate object (IMBNodeViewControllerDelegate protocol). When testing the framework through its test application (iMediaTester), you may alternatively add an Application Password to your login keychain with account set to imb_facebook_app_id and password set to your Facebook app id.

Flickr Access Configuration

T.b.d.

Migrating from iMedia 2 to iMedia 3

While building your project using the new iMedia framework, you may notice some changes:

  • The location property of IMBObject is an NSURL now
  • There are no "object promises" in Drag & Drop any more. Instead IMBObjects are placed on the pasteboard. You may like to call imb_containsIMBObjects from NSPasteboard+iMedia.h to check wether a drag pasteboard holds iMedia objects.
  • Thumbnail loading is async now and in case you utilized this operation, you may like to observe the imageRepresentation property of IMBObject after triggering a loadThumbnail operation
  • A couple of subclasses of IMBObjectViewController have been renamed. Have a look at commit 0080941501f2cfffb0772180161e79b08738e4e8 of March 28th 2012 for details

Accessing your app's URLs

In case you are moving from a none-sandboxed version of your app to a sandboxed one, you need to think about migrating your data. For example, your current document file may hold an URL to an image, which is located outside the Pictures folder. Due to the sandboxing constraints, you might not be able to access that image any more.

To make the process for the user as painless as possible, you may want to find a common ancestor of all images used in your document and ask the user to give you permission to access that folder:

  1. Collect all URLs you can't access. You may like to use imb_accessibility from NSURL+iMedia.h for this purpose.
  2. Find a common ancestor folder: + (NSURL*) commonAncestorForURLs:(NSArray*)inURLs from IMBAccessRightsController.h
  3. Get permission from the user to access that folder. Have a look at _showForSuggestedURL:name:completionHandler: in IMBAccessRightsViewController.m for an idea of how to do this
  4. Now that you have permission, change all URLs into app scoped bookmarks

Object Identifiers

Persistent IMBObject identifiers are no longer depending on class names because changing a class's name would affect the identifier. iMedia now provides:

  • -[IMBObject identifier]: a unique identifier for this object at runtime (i.e. explicitly not guaranteeing to be identical across sessions)
  • -[IMBObject persistentResourceIdentifier]: a unique persistent resource identifier for this object
  • -[IMBParser iMedia2PersistentResourceIdentifierForObject:]: to assist you in migrating iMedia 2 persistent resource identifiers to iMedia 3 persistent resource identifiers in case you persisted resource ids in your iMedia 2 based app (e.g. to utilize the badges feature)

Enjoy!