I have to admit that with the release of iOS 8 I am a bit confused about dynamic and static frameworks in iOS.
I am looking for a way to distribute a library that I created, and I need to support iOS 7 and above. (Note: This will be a proprietary framework. I cannot use cocoa pods, and I also cannot distribute the source). Here is what I already know:
iOS 8 introduced "embedded frameworks" for iOS, but, as I understand, they do not work for iOS 7, only for iOS 8 and above.
I have the option of distributing my library as a static library (.a file) and also distribute the headers. I know that this is a common way of dealing with the situation, but I would like to find something simpler than that (and also to bundle some resources with it, if possible).
I have also found that iOS 7 does not support dynamic .framework libraries (only static) because it doesn't support dynamic linking. But iOS 8 does, as well as static linking.
And here are my questions regarding this information:
I saw that I can create a .framework target, and make it static, by changing the Mach-O type to "static library. Would that be enough in order to support iOS 7 without any problems, and also to distribute my library as a .framework bundle? If so, why is "embedded frameworks" in iOS 8 that big of a deal, as many resources on the internet are suggesting? Am I missing something?
Is it necessary to codesign the .framework just as I do with any other application I make?
What if I need to include other resources (like Core Data or Images) with my .framework file? Will I need to make a separate .bundle file for that?
Before iOS8, Xcode only allowed the option of creating static libraries for iOS. The common problem with that was we had to ship the binary and headers separately.
Later, some developers came with the idea of creating 'static frameworks'. [the .framework is just a folder with symbolic links to the lib and the headers]. One such example is https://github.com/jverkoey/iOS-Framework
This option will work for iOS 7 or 8 or before that. Because they are just static libraries with the convenience of bundling the headers files along.
As for your questions of the resources, we would need to bundle them in '.bundle'.. For shipping them i am not sure if we can enclose them in the .framework folder.. In the past i used to ship my libs as a static framework and bundle...
However the above option will not work for you if you use Swift. Xcode does not support building static libraries that include swift code.
You must go with Dynamic frameworks if there is swift usage. In theory, Dynamic frameworks work in iOS7.. But, i think iTunes Connect will reject if the app is targeting iOS7 and uses Dynamic frameworks :-).
Hope this helps
Static vs Dynamic linking
static or dynamic in name usually points into a Linking[About] type
Frameworks can be static or dynamic[Check static or dynamic]
You can change the format of library that will have an impact on a Linker by changing Framework target -> Build Settings -> Mach-O Type[About] to Static Library or Dynamic Library. By default Xcode has Dynamic Library value.
Depends on this setting different types of binary will be generated
After you successfully configure a consumer[Link vs Embed]
Static Linker ld: at compile time will include all code from the static library into the executable object file.
Dynamic Linker dyld: at load/run time will try to find the embedded framework using #rpath[About] and link it
[Vocabulary]
With Xcode 9 onwards you can create static frameworks for Swift as well. This is possible due to ABI source compatibility. All you need to do is just change the Mach-O type under build settings of the framework target.
This technique is also applicable to Hybrid Frameworks(frameworks with Swift and Objective-C code).
I don't have all the answers but I'll try to address some of your questions here.
You will get a warning for using these frameworks in iOS 7, however that's all it is, a warning. See this answer.
You can include other resources like CoreData however you'll need to create them in code manually. Here's a tutorial showing how to create a core data model.
You have to code sign dynamic libraries for iOS.
You need to make sure your framework supports both simulator and device architectures if you're planning to distribute it.
Swift does not work in static lib. If you have to use dynamic framework, you have to set min iOS to 8.0 because AppStore reject ios 7 with dynamic framework
Related
I have read many articles about static/dynamic library/framework. So my understanding is (let me know if it's inaccurate):
Framework = Library + Bundle
Static = Linking at build time
Dynamic = Linking at run time
In Xcode, we have "Static Library" and "Framework". Which raises a few confusing points:
Why there's no "Dynamic Library" option?
Given that we can already link framework statically, why do we still need a "Static Library"? (isn't StaticFramework = StaticLibrary + Bundle? )
Why there's no "Dynamic Library" option?
Because Dynamic Library is not permitted for iOS apps at beginning.
Given that we can already link framework statically, why do we still need a "Static Library"? (isn't StaticFramework = StaticLibrary + Bundle? )
Because old Xcode only support Static Library.
Static Framework was added later, and they keep the Static Library.
There are many concepts that must be clear
Libraries have two categories based on how they are linked to the executable file
Static library .a, .so. link at compile time. wiki
Dynamic libraries .dylib .dll etc. link at runtime. only apple can use it for iOS for some safe reason, we cannot build this.
ps, a special kind in apple platform
Text Based .dylib stubs — .tbd
Framework
Framework is a package that can contain resources such as dynamic libraries, strings, headers, images, storyboards etc.
vs Libraries, Framework has more features
Framework also has static and dynamic
iOS 8 later, we can use a dynamic framework, why Apple releases this. maybe Extension and App share code
this Dynamic Framework for iOS is named embedded frameworks, because when we build the app copy the framework in app bundle.
so the embedded framework is different from system dynamic Frameworks like UIKit.Framework
Why there's no "Dynamic Library" option?
the embedded library is allowed with the Framework option, but dynamic framework shared in muti app is also not allowed
Given that we can already link framework statically, why do we still need a "Static Library"? (isn't StaticFramework = StaticLibrary + Bundle? )
well, Xcode not only support Objective-c and Swift, but also support C, C++ which may use the static library
I'm a novice on XCode and I'm making an iOS Framework with Swift2, including 3rd party libraries(*.a) and frameworks.
I want to provide it as API to others, but I also want to hide the 3rd party libs and frameworks files from my framework distribution files because they are private.
Therefore I just want to open API interfaces and classes I defined.
Is it possible? How to configure my build options?
You can do that but there are some things you need to consider:
You cannot embed one framework into another one. That means if you do not have the sources to a particular framework you have to ship it alongside your own framework. If you have the sources you may consider compiling them into your framework directly.
Depending on the sources that you use in the framework you might have to do some post processing of the framework to obfuscate private headers etc. For example, if you use Objective-C or C code alongside Swift you definitely need to do some post processing of your *.framework file to hide any API that you want to keep private.
If you use Swift code in your framework please be aware that your framework can only be used by someone with the same Swift compiler version due to the absence of an ABI. That means binaries produced by one compiler version have a high likelihood of being incompatible to a newer version of the compiler.
Static linked libraries can be linked and therefore "merged" into your framework binary directly. You just need to make sure that you have a compatible binary for the architecture you want to target, e.g., you cannot use a static linked library that was build for simulator and link it against your framework that you want to build for the actual iOS device.
If you use Swift in your framework, the users of your framework need to include the Swift dylib libraries in their app bundle - either by using Swift in the app or by enabling the Embedded Content Contains Swift Code build setting.
I was able to create iOS Framework for Xcode as shown in that video:-
https://youtu.be/86cPaa3FrRg?t=4m55s
On 5:00 they say that framework must be added to Embeded Binaries.
If I add it to Embeded Binaries then it works.
It is not required to add GoogleAds.framework to Embeded Binaries.
Adding to Embeded Binaries looks a bit "hacky" comparing to Googles solution.
So I think this tutorial is missing some step.
My question is: How can I make a framework that works without adding it to Embed Binaries?
tl;dr They are both frameworks, but they are different types.
The term "framework" is ambiguous. On OSX it means a packaged dynamic library (i.e. .dylib, headers, other stuff), however before iOS 8 users could not create dynamic libraries so "static frameworks" were invented to provide packaged static libraries (i.e. .a, headers, other stuff).
If the framework you created needs to be packaged with the app as an embedded binary then it sounds like a dynamic framework, however if Google Ads doesn't then I suspect it's a static framework. It doesn't need to be embedded as it's already been linked into the app binary.
If you want to know how to create a static framework, then start here, or Google for "ios static framework".
Prior to iOS 8, developers shipped unsupported frameworks that were cobbled together with static libraries by mimicking the directory structure of Apple's frameworks. They worked, but they were a pain to build, and they were static—not dynamic—libraries.
As of iOS 8, Apple officially supports building third-party dynamic frameworks in Xcode. These types of frameworks are code-signed and must be placed in the Embedded Binaries for your app. If you link against them but fail to put them in Embedded Binaries, you will get an exception when attempting to run on device and your app will crash.
In the long-run, I would expect the hacked together frameworks like GoogleAds.framework to disappear now that official framework support is available. This means you'll have to get used to putting frameworks in Embedded Binaries.
Unless you need to support iOS 7 with your code (in which case official frameworks are not an option, because they only work on iOS 8), I would advise against creating an unsupported type of framework at this point.
Up until iOS7, Apple did not support dynamic linking due to security concerns. Code reuse between developers usually relied on static libraries, which were built as part of the executable of the app.
Introducing extensions in iOS8 seems to change this a bit, because extensions are separate executables. Sharing code between an extension and its containing app is done via a framework. Apple is saying this in their release notes:
Frameworks for iOS. iOS developers can now create dynamic frameworks.
Frameworks are a collection of code and resources to encapsulate
functionality that is valuable across multiple projects. Frameworks
work perfectly with extensions, sharing logic that can be used by both
the main application, and the bundled extensions.
Emphasis is mine.
Source: https://developer.apple.com/library/content/documentation/Xcode/Conceptual/WhatsNewXcode-Archive/Articles/xcode_6_0.html#//apple_ref/doc/uid/TP40014509-SW14
Further, in the extension dev guide, they explain that you can share code between an extension and the containing app via a "embedded framework".
Source: https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html#//apple_ref/doc/uid/TP40014214-CH21-SW1
My question is - what is an embedded framework, how does it differ from a dynamic framework, and will we really see proper dynamic linking in iOS8? All the documentation I've read seems ambiguous about this.
"Embedded" and "Dynamic" frameworks don't refer to the same aspect of frameworks. They are not the opposite of one another. First, let's define what's a framework: in Apple lingo, a framework refers to some compiled code + the public headers of said code.
Now a dynamic framework is a framework whose code was built as a dynamic library. It is the opposite of a "static" framework, where the code would be built as a static library. In case you're wondering, Wikipedia has a very nice explanation of what's the difference between a static and a dynamic library.
And finally, an embedded framework is a framework that is packaged within an app, as opposed to being installed system-wide, in "/System/Library/Frameworks" for example.
An embedded framework is simply one that's included in the app bundle, rather than a global framework which is installed in system directory.
Dynamic Frameworks doesn't means dynamically linked framework. Apps still just work in a sandbox environment. It's not like your custom frameworks are going to be installed with the iOS. Each one of your apps that uses the common framework that you've developed is going to be copied inside every app's bundle.
You can see this for yourself. Go to your Xcode's Derived Data directory and inside the app's data, you'll find all the embedded frameworks copied.
The only new thing with creating Frameworks with iOS 8 compared to static libraries is that the public header files and assets gets bundled within the Framework. If you've been doing this sort of things with earlier versions of Xcode, you'll remember the pain with supplying public headers and then adding the search path within Xcode settings and for assets we had to pass in a separate bundle.
This only downside of using Frameworks that I see is that now we can't simply use lipo to generate a fat static library for all kind of architectures.
IMO Apple is using the word 'dynamic' to suggest 'independent'.
Watch WWDC2014 - Building Modern Frameworks for more details.
There is a number of questions (some of them with answers) about creating custom dynamic frameworks for iOS. My practical experiance shows that on iPad2 and iPad3 one can use custom dynamic frameworks and it works. On iPad1 it doesn't work. So my question is. Did it become possible to use dynamic frameworks on new versions of iOS?
Apple doesn't allow you to create your own dynamic frameworks for the iOS platform. There is however a way to package up your static library and using in a similar way as a framework.
Did you see this post?
I particular check out this GitHub repo, this is what I used to get up and running, very simple explanations: https://github.com/jverkoey/iOS-Framework
Basically you will create a static library and create multiple targets for each platform - simulator and device and one last target which I usually call "build and merge", this target has a script that takes the resulting libraries for device and simulator, and packages them up in a folder called xxxxxx.framework, inside is the standard structure and it contains your static libs, when you use this in other projects you import the framework to that project and include the header files like you would any other real dylib framework.