Xcode 6 and Embedded Frameworks only supported in iOS8
Asked Answered
E

15

69

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) 
Enjoy answered 18/9, 2014 at 10:11 Comment(2)
Yes, you can use a dynamic framework on iOS 7: quellish.tumblr.com/post/103107323582/…Shakitashako
@Shakitashako good to know, had a talk with Apple engineers at WWDC '14. They didn't suggest this technique. That said, it could be a possibile workaround in some cases.Enjoy
A
40

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 :)

Agnate answered 24/2, 2015 at 18:39 Comment(11)
This does not works and it gives out an error while validation of the iPA.Tease
It says "found an unexpected Mach-O Header code :someNumbers.." while validating.Tease
I didn't go so far as app review but this worked for me all the way to submitting a binary to iTunes connect.Pe
Similar to what Anthony said, I was also able to validate an ipa against iTunes Connect using this method. The app also runs on a iOS 7 device as well as iOS 8 device, with just some short testing. Good answer.Dive
Can anyone approve this still works when submitting to the Appstore?Extinguish
No issues on my side @ExtinguishAgnate
Sorry for the hassle, but let me get this straight. You've started a new project in xCode 6 using the 'dynamic framework' template and you're able to submit the app to the Appstore with iOS 7+ support? How about iOS 6?Extinguish
6 is fine as well, unless framework type is set to Static LibraryAgnate
@MaciekCzarnik Is this working for Swift Framework too?Kosiur
I'm not sure about Swift @Lightygalaxy, did you check it?Agnate
Glad to hear it @DawnSong :D Good luck with your framework!Agnate
E
30

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

Enjoy answered 18/9, 2014 at 10:31 Comment(15)
Just so I'm clear, you're saying that your results show that, even though the dynamic framework can run on iOS 7, the App Store Submission Validator will reject an app that attempts to use a dynamic framework on iOS 7?Confucius
Yes it's exactly what I had here, after adding the arm64 support, requested when you have a modern iOS8 app that means at least one contained app/widget plu embedded framework (as for apple docs). Then iTunes Connect will reply that way.Enjoy
We're thinking there isn't much hope that Apple will allow them to run on iOS7 ever, code signing issues on the dynamic framework.Confucius
As far as I know and found you cannot deploy the embedded framework if you build it for iOS7. In developmentor intranet distribution environments it works as I showed here.Enjoy
After updating to Xcode 6.1, this method doesn't work anymore. Still keep returning error: embedded dylibs/frameworks are only supported on iOS 8.0 and later. Anyone knows how to fix it?Vermicelli
guys, same issue with dynamic library and ios7. If i rewrite dynamic to static - it will be solve issue? Or then my widget will stop work?Buntline
Was your project rejected?I am having same issue could you please let me know if it will be submitted or not? If not how to use embedded frameworks with iOS7 supported application.Cchaddie
@Cchaddie The IPA did not pass the iTunes Connect validation during the XCode submission phase, before completing the upload to the app store. An interesting case was depicted by BigCheesy below here, that could help you, even if I'm not sure it would work for all cases. Good luck!Enjoy
How we can use dlopen() in Xcode??? Any Example ?? check tis link Deploying a Containing App to Older Versions of iOS developer.apple.com/library/ios/documentation/General/…Eclair
@loretoparisi, do you remember what version of the Xcode you were using when the validation failed? And if that isn't the latest version have you tried again with Xcode 6.1? (I've heard reports that it may be possible in latest version).Prudence
@OliverPearmain XCode 6.0.1 and I did not checked on XCode 6.1, since I moved to iOS Universal Framework, that at the end is more versatile github.com/kstenerud/iOS-Universal-Framework and it works in most of XCode/iOS.Enjoy
Interesting note from iOS 8.3 Beta about app extension, embedded frameworks and ARM64 - : - App extensions need an arm64 slice to run on 64-bit devices. If you try to run the armv7 slice on a 64-bit device it won’t work. - Apps need to have an arm64 slice if the bundle contains a framework that both the app and the app extension link against.Enjoy
Any chance you could EDIT your answer with a note at the TOP (not the bottom) that says, 'This answer isnt an answer'.Scevo
where is the "in the void Embedded Frameworks section." in Xcode? I don't see that under GeneralAsthenic
I second @xta: Where is the "void Embedded Frameworks section"?Rica
N
12

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.

Nettienetting answered 5/10, 2014 at 14:40 Comment(2)
BigCheesy I have read that documentation for dlopen but didnt understand a thing.Is it possible to use embedded frameworks with iOS7Cchaddie
@Cchaddie iOS 7 runtime - no. With deploy target iOS 7 of main app - yesArundinaceous
M
4

Fixed the error in xcode 6.1.1

using vim or vi open the project.pbxproj file.

At the end of the file (search for 8.1) , there would be Begin XCBuildConfiguration section

Look for your framework.

In out case even though the deployment target was set to 7.1 via Xcode -> general in target settings, the entry in the file had 8.1 for both debug & release

Here's the old file section looks like:

CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = ENFramework/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";

New section looks like :

CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = ENFramework/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 7.1;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";

Now we don't get error just a warning (but works on iOS 7.1 device) : ld: warning: embedded dylibs/frameworks only run on iOS 8 or later

This looks like an xcode bug which incorrectly sets different ios targets and then causes error.

Masterly answered 23/1, 2015 at 6:20 Comment(3)
Did you confirm it was not rejected during the submission process?Soulless
does not works and the version does shows correctly after wards also.Tease
This is the only answer on this page that has worked for me. Simply changed IPHONEOS_DEPLOYMENT_TARGET from 8.2 to 7.1, saved the project file and it built successfully. Thank you.Threescore
E
4

Going deeper on Apple Documentation I found out about dlopen command, which is used to make the linking of the libraries on some conditions, depending on system versions and libraries supported.

dlopen example of use: Is the function 'dlopen()' private API?

So let's look at the solution provided by Apple Docs:

Deploying a Containing App to Older Versions of iOS

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.

The mechanism that lets you do this is the dlopen command, which you use to conditionally link and load a framework bundle. You employ this command as an alternative to the build-time linking you can specify in the Xcode General or Build Phases target editor. The main idea is to link embedded frameworks into your containing app only when running in iOS 8.0 or newer.

You must use Objective-C, not Swift, in your code statements that conditionally load a framework bundle. The rest of your app can be written in either language, and the embedded framework itself can likewise be written in either language.

After calling dlopen, access the embedded framework classes using the following type of statement:

MyLoadedClass *loadedClass = [[NSClassFromString (@"MyClass") alloc] init];

IMPORTANT

If your containing app target links to an embedded framework, it must include the arm64 architecture or it will be rejected by the App Store.

To set up an app extension Xcode project to take advantage of conditional linking

  1. For each of your contained app extensions, set the deployment target to be iOS 8.0 or later, as usual. Do this in the “Deployment info” section of the General tab in the Xcode target editor.
  2. For your containing app, set the deployment target to be the oldest version of iOS that you want to support.
  3. In your containing app, conditionalize calls to the dlopen command within a runtime check for the iOS version by using the systemVersion method. Call the dlopen command only if your containing app is running in iOS 8.0 or later. Be sure to use Objective-C, not Swift, when making this call.

Certain iOS APIs use embedded frameworks via the dlopen command. You must conditionalize your use of these APIs just as you do when calling dlopen directly. These APIs are from the CFBundleRef opaque type:

CFBundleGetFunctionPointerForName
CFBundleGetFunctionPointersforNames

And from the NSBundle class:

load
loadAndReturnError:
classNamed:

In a containing app you are deploying to versions of iOS older than 8.0, call these APIs only within a runtime check that ensures you are running in iOS 8.0 or newer, and call these APIs using Objective-C.

Egide answered 10/4, 2015 at 22:58 Comment(0)
T
2

We tried running the latest code on the following configurations:

iOS 8+ — iPhone 5s iOS 7.1.2 — iPhone 4 iOS 6.1.3 — iPad 4

The App is working fine on all the three devices but the warning is present in the Xcode while compiling . "embedded dylibs/frameworks only run on iOS 8 or later”

Also I tried to Archive the App in order to submit it to the app store it went on fine.

Also, found out a link where in an apple developer stated this to be a bug https://devforums.apple.com/message/999579#999579

Tease answered 24/12, 2014 at 13:53 Comment(1)
Although when we go and use distribution profile and try to submit the app to the itunesconnect. it gives out the error The MinimumOSVersion of framework "..." is invalid. The minimum value is iOS 8.0;Tease
C
2

Just for the record... I had this issue when changing a project from iOS8 to iOS7 deployment type.

The app used cocoapods and no custom embedded frameworks.

I had to change the main project two targets
Application
Application-Test

Changing Mach-O Type to static (from above answer).

Then on the cocoapods project. Under each sub pod project changing the Mach-O type to static, leaving the main pod Project Mach-O setting to blank.

Capacity answered 19/5, 2015 at 19:44 Comment(0)
M
2

I set the Mach-O Type to EXECUTABLE and it worked for me. Setting it to Static, Dynamic or Bundle created other errors when I ran it.

Target > "Your App" > Build Settings > Linking > Mach-O Type > Executable

Masturbation answered 22/6, 2015 at 12:56 Comment(1)
Worked for me too on ios 9.3.2, this is only solution.Dissuasion
H
1

I solve this problem following way : Use same deployment target in both target "Embedded Framework" and "main App" target.

Hitt answered 8/11, 2014 at 10:49 Comment(0)
B
1

So, temporary, i said no to dynamic library, while many devices on iOS 7. How i solved my problem. I was need lib for transferring model between app and extension. So, i put my model to JSON string into shared container. And it works like a charm.

Buntline answered 25/11, 2014 at 15:12 Comment(1)
This is a good option to serialized/deserialize the object model and share it through the container app and the extension. The problem is if you have a more complex framework and you need to share the logic. Through the sandbox where the embedded binary of the extension and the app live, you can share a filesystem folder, so you can share a whole database as well.Enjoy
D
0

When you use dynamic library on ios you must code signed the library. In the Xcode 6, you should select the "Code Sign On Copy". And with the Xcode5, you should sign the library by your self with run script. like :

LOCATION="${BUILT_PRODUCTS_DIR}"/"${FRAMEWORKS_FOLDER_PATH}"
IDENTITY="iPhone Developer: xxxxx"
codesign --verbose --force --sign "$IDENTITY" "$LOCATION/BeeFramework.framework/BeeFramework"
Diacid answered 15/12, 2014 at 6:29 Comment(2)
This really works, do as this can make your app run. But Apple may not allow to do that.Diacid
Yes, this does makes the app run but this fails during the validation process of itunesconnect.Tease
D
0

Remove the use frameworks! from your PodFile if you want the Framework to work in iOS 7.0. i.e. run pod deintegrate command, modify your PodFile and then rerun the pod install command

Also after this, I had to add all the .h file's of the Framework in the Bridging file, that fixed the issue. Also remove the import TestLibrary from the swift files

Dagney answered 8/12, 2015 at 12:56 Comment(0)
R
0

I had a bug when updating to xcode 7.3. And I had solution for me. - Change targets in pods project -> 7.0 - Hope it useful! attack

Robrobaina answered 25/3, 2016 at 1:21 Comment(0)
N
0

I was running into an issue where i needed to include some libraries as embedded frameworks otherwise i received the above error and when I did just that, I received errors when submitting to the app store.

My solution was to use Pods and make sure you uncomment the "use_frameworks!" line.

Navarre answered 30/5, 2016 at 0:3 Comment(0)
R
0

iOS Dynamic framework pre iOS v8

Dynamic framework aka Embedded framework is supported from iOS v8, but you can try to change Mach-O type[About] to Dynamic Library (which is set by default for supported target)

Dynamic linking error[About]

dyld: Library not loaded: @rpath/<some_path>

It is an dynamic linker error which links binary in load or runtime

[Vocabulary]

Rabblerouser answered 26/9, 2022 at 15:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.