Xcode 6 and Embedded Frameworks only supported in iOS8

When using an embedded framework (dyld) in Xcode 6.0.1 with deployment target less that iOS 8 I get:

  • Build is successful
  • Runtime library loading error

Error:

dyld: Library not loaded: @rpath/ObjectiveLyricsTouch2.framework/ObjectiveLyricsTouch2        
Referenced from: /private/var/mobile/Containers/Bundle/Application/DC65ACA9-98E5-46CD-95F8-829D3416F6C0/musiXmatch.app/musiXmatch
Reason: image not found
(lldb) 

Solution 1:

For some time I was thinking that this is my problem as well, but for normal apps (non-iOS-8-extension) you just need to change one build setting in your casual Xcode 6 iOS Universal Framework target (set Mach-O Type to Static Library):

Set it to Static Library

There should be no problem with iTunes Connect and iOS 7 after that :)

Solution 2:

So, after digging around I came out with the solution

Supposed to have yours MyEmbeddedFramework.framework to add to the app, do this

  1. Remove MyEmbeddedFramework.framework in the tab General > Embedded Binaries
  2. Remove the Build Phases > Copy Phase "Frameworks" if you have MyEmbeddedFramework.framework there.
  3. Clean Build Folder
  4. Move the MyEmbeddedFramework.framework in the void Embedded Frameworks section.
  5. You will see now that a new Build Phase > Embedded Frameworks is created by XCode6 (not you, it is done automatically)
  6. Now if you have 5, it should run without erros.

So to recap, to make it works you should see MyEmbeddedFramework.framework in

A) General > Embedded Binaries General > Embedded Binaries

B) Build Phase > Embedded Frameworks Build Phase > Embedded Frameworks

It worked fine on iPhone5/iOS8 not on iPhone4S/iOS7 where I get:

dyld: Library not loaded: @rpath/ObjectiveLyricsTouch2.framework/ObjectiveLyricsTouch2 Referenced from: /var/mobile/Applications/739D9C44-3B91-4D4F-805B-83BE66C9CBCA/musiXmatch.app/musiXmatch Reason: no suitable image found. Did find: /private/var/mobile/Applications/739D9C44-3B91-4D4F-805B-83BE66C9CBCA/musiXmatch.app/Frameworks/ObjectiveLyricsTouch2.framework/ObjectiveLyricsTouch2: incompatible cpu-subtype: 0x0000000B in /private/var/mobile/Applications/739D9C44-3B91-4D4F-805B-83BE66C9CBCA/musiXmatch.app/Frameworks/ObjectiveLyricsTouch2.framework/ObjectiveLyricsTouch2

The problem was in the EmbeddedFramework. I had to

1) Set Architecture to default 2) Set Valid Architectures to: armv7, armv7s and armv64 (as Apple suggests armv64 is needed to have Embedded Frameworks working).

Then I was able to run the app with an embedded framework on

  • iPhone5S/iPhone5C iOS8
  • iPhone5S/iPhone5C iOS7
  • iPod 5th gen / iOS7
  • iPhone4S / iOS7
  • iPhone4 / iOS7

Anyways when submitting to iTunesConnect I get some errors for the Minimum Required Version:

  • The MinimumOSVersion of framework "..." is invalid. The minimum value is iOS 8.0;
  • Invalid Architecture: Apps that include and app extension and a framework must support arm64;

Embedded Framework Issues

Solution 3:

As of right now there is no way to use an embedded framework to share code between an app and widget and have it run on iOS 8 as well as iOS 7 & previous.

Here's some more reading on that http://atomicbird.com/blog/ios-app-extension-tips

Frameworks vs. iOS 7

If you are sharing code between an app and an extension, one nice way to do so is to create your own embedded framework to hold the code. On iOS 8 it'll load dynamically for both cases, so you're set.

If you still support iOS 7 (or earlier), it's not so clear cut. Embedded frameworks don't work there. The App Extension Programming Guide breezily notes that you can use dlopen to deal with this. With that approach you write code to load the framework dynamically at run time rather than rely on iOS loading it for you, if you've verified that the code is running on a version of iOS that supports doing so.

But how do you use that code on iOS 7? You don't. If your shared code is in an embedded framework, there's no way to execute it on iOS 7. It's just unavailable.

The dlopen approach might be handy if you only need the shared code on iOS 8. If you need it on iOS 7, you'll need to include it in the app target. And once you do that, you have no need of the framework. You could still use a framework for the app extension, but doing so is not actually useful. You'd be doing the work of creating the framework but not getting any benefit from it. Just include the shared code in both targets.

And from Apple's extension guide https://developer.apple.com/library/ios/documentation/General/Conceptual/ExtensibilityPG/ExtensibilityPG.pdf

If you link to an embedded framework from your containing app, you can still deploy it to versions of iOS older than 8.0, even though embedded frameworks are not available in those versions.