iOS: Binary Framework using Swift - ios

If I make binary framework using swift, will it support objective C projects and what will be minimum supported version? is there any other drawbacks compare to objective c framework?

Yes, Binary frameworks in Swift will support Obj-C projects. Please ensure Obj-C related settings in Build Settings of Framework project are enabled. It will be enabled by default to create bridging header to inter-operate with Obj-C.
Minimum supported OS Version
With Swift ABI stability achieved in Swift 5 and now, module stability in place, there is no need to ship Swift source code while sharing the frameworks. If we want to share the library, Binary framework (xcframework) can be created and shipped without worrying about Swift compiler version incompatibility errors.
Since binary frameworks is dependent on module stability, and in turn, ABI stability, it needs Swift standard library in OS itself. Apple started including Swift standard library in OS when Xcode 10.2 was released, in which Swift 5 was supported. It means, iOS < 12.2 will not have Swift standard library. So, in case of iOS version < 12.2, all swift apps will have their own runtime library included in it. In case of pure Obj-C projects running in iOS < 12.2, ensure "Always Embed Swift Standard Libraries" to Yes in Build settings. Otherwise, it will crash in runtime. So, with respect to OS versions, we see this as the only limitation.
I was able to run a pure Obj-C project using Binary Framework in Swift, even in iOS 9 simulator.
Advantages of using Binary Framework
Binary Framework in swift can be created for all devices, simulators and for all platforms (iOS, MacOS, watchOS, tvOS). It's a single library for all platforms.
We need not ship actual swift source code in framework.It has resolved Swift compiler incompatibility issues.
Interoperability with Obj-C is simple and effortless and can't vouch same on vice-versa.
Hope it helps.

Related

How to prebuilt libraries to be compatible with future swift versions

We are prebuilding some libraries (mainly with carthage) for some of our projects to reduce development times. These libraries are not updated very often, but we want to update our XCode versions pretty fast.
Now every time a new XCode brings a new swift version, we are seeing this incompatibility issue
File.swift:4:8: error: module compiled with Swift 5.3.2 cannot be imported by the Swift 5.4 compiler: /......./Debug-iphoneos/Alamofire.framework/Modules/Alamofire.swiftmodule/arm64-apple-ios.swiftmodule
How can I pre-build my dependencies in a way that a swift update wont affect it and I dont have to re-build the dependencies with every xcode update (I thought thats what ABI stability was for? How can I activate that?)
It sounds like you're misunderstanding what ABI stability enables. The main benefit is that it allows the OS to include only one version of the Swift standard library, and for all Swift binaries to share it. What you want is "module stability". From the docs on ABI stability:
ABI stability is about mixing versions of Swift at run time. What
about compile time? Right now, Swift uses an opaque archive format
called “swiftmodule” to describe the interface of a library, such as a
framework “MagicKit”, rather than manually-written header files.
However, the “swiftmodule” format is also tied to the current version
of the compiler, which means an app developer can’t import MagicKit if
MagicKit was built with a different version of Swift. That is, the app
developer and the library author have to be using the same version of
the compiler.
To remove this restriction, the library author needs a feature
currently being implemented called module stability. This involves
augmenting the opaque format with a textual summary of a module,
similar to what you see in Xcodeʼs “Generated Interface” view, so that
clients can use a module without having to care what compiler it was
built with.
This is not yet supported in any version of Swift.

Can I wrap an iOS Swift Framework into a static library with C API?

I'm building an iOS app that uses ARKit, which constrains me to use Xcode 9.3, Swift 4.1. Now I have a Swift 4.0.2 framework (3rd-party) which I want to use in this app.
To the best of my knowledge, I can't use Swift 4.0.2 for my project (due to ARKit dependency).
Solutions I've come up with:
The obvious solution would be to get a Swift 4.1 version of the 3rd-party framework. However, I'd have to request that again when Swift 4.2+ comes out, etc.
Request an ObjC library from the 3rd-party.
Building a static Swift library (possible as of Xcode 9 beta 4) from the framework - but this still results in a Swift version dependency.
So I'm trying to build a static library that has a C API (i.e. a stable ABI) as a repackaging/wrapper for this Swift framework and then work with this lib.a.
Is this technically even possible? Has anyone ever done this?
Is there a better solution which I'm missing?

Is Swift ABI compatible between minor versions?

I know Swift is not yet ABI stable, but does that only count for major versions of Swift?
Is there any guarantee that minor or patch versions (under semantic versioning) of Swift are ABI stable?
I'm guessing there is no guarantee here, but just wanted to double check if anyone has come across anything detailing ABI stability for different minor/patch versions of Swift.
Also, if I use a Swift binary framework compiled with a different version of Swift I get a compiler error usually. If I don't get a compiler error in my project does that mean it is safe, or could there still potentially be runtime issues with a slightly different (patch version) of Swift?
Update 3
We also have module stability, starting with Xcode 11, with the help of the newly introduced .swiftinterface files. One caveat, though, is that the code will have to be build with the -enable-library-evolution flag. More details here.
Update 2 Module stability is scheduled for Swift 6: https://swift.org/blog/abi-stability-and-more/#module-stability
This is an excerpt from the Swift evolution repo.
Update Swift 5 comes with some ABI stability:
The Swift 5 release will provide ABI stability for the Swift Standard Library.
Unfortunately, not yet. For Swift 4, they state this here: https://swift.org/blog/swift-4-1-release-process/.
Swift 4.1 is not binary compatible with 4.0. It contains a variety of under-the-hood changes that are part of the effort to stabilize the Swift ABI in Swift 5.
Hopefully we'll get ABI stability in Swift 5
I think we should know what is ABI stability firstly, After that your confusion has already been removed.
Today, the latest version of Swift is 3.1, so chances are if you ship an app tomorrow, your app bundle will contain the Swift dynamic libraries for 3.1, however, there are plenty of apps in the store right now which link 3.0, 2.3, and probably even some older apps that link 2.1 and earlier. Nothing is stopping me from downloading your app (on 3.1) and my app (on 2.3) and running them side-by-side on my iPhone with iOS 10.3, since both apps link against their own bundled version of Swift. It's exactly the same as you bundling Alamofire 4.4 and while I bundle 3.0.
When a language is ABI-stable (Application Binary Interface), that means it is packaged and linked with the operating system itself, in this case: iOS. The Swift code you compile on your computer has a binary interface into the operating system itself rather than any dynamic library you bundle with your application. Because of this, Apple has to be able to guarantee that my Swift code, when compiled to machine code (bitcode, LLVM-IR, yada-yada), will be able to interface properly with the rest of the operating system, and (probably more importantly) will not break between versions of iOS / Swift.
As it stands today, the Swift language specification and compiler are not in a state where the Swift team would feel comfortable making this promise of ABI-stability; changes to Swift are still too frequent and the roadmap is still too long. As soon as the Swift library is merged into iOS, it becomes much much harder to make big changes.
Why does it matter?
Yes, the bundle size of your application will decrease because you will no longer have to include the Swift standard library in your Frameworks folder, which is nice.
Language changes will be smaller / less frequent, so you won't have to worry about events like migration from Swift 2 -> 3 (I'm still scarred from that)
Developers will be able to create 3rd-party libraries written in Swift and distribute pre-compiled frameworks (binaries), because they no longer need to bundle the Swift standard library into their framework, and will instead be linking against the same version of Swift as your app (the one packaged with iOS).

How does iOS7 understands Swift Code? Is there any Swift support by OS?

Here is my short assumption on that currently looking more on it.
Application with Swift code bundles Swift specific standard libs with Swift, Apple has changed how standard libraries are shipped. With Objective-C, all of the standard libraries, system frameworks, and the runtime itself, were shipped with the OS. But With Swift, Apple trying to ship a specific version of the standard library with your app.
Please share your thought on that.
Found Interesting - Compatibility Blog
According to that - In fact, you can target back to OS X Mavericks or iOS 7 with that same app. This is possible because Xcode embeds a small Swift runtime library within your app’s bundle. Because the library is embedded, your app uses a consistent version of Swift that runs on past, present, and future OS releases.
Any other discussion warm welcome!

Swift compatibility between versions for a library

I'm distributing libraries for other developers to use (http://empiric.al). I've noticed that between swift versions, even 2.0 to 2.1, I'll get Module file was created by a (newer/older) version of the compiler.
I need to be distribute in a future-proof way.
How can I make sure my compiled frameworks can be used by newer versions of Swift in the future so I don't have to recompile as soon as Apple puts a new beta out?
From Apple's website:
Binary Compatibility and Frameworks
While your app’s runtime compatibility is ensured, the Swift language
itself will continue to evolve, and the binary interface will also
change. To be safe, all components of your app should be built with
the same version of Xcode and the Swift compiler to ensure that they
work together.
This means that frameworks need to be managed carefully. For instance,
if your project uses frameworks to share code with an embedded
extension, you will want to build the frameworks, app, and extensions
together. It would be dangerous to rely upon binary frameworks that
use Swift — especially from third parties. As Swift changes, those
frameworks will be incompatible with the rest of your app. When the
binary interface stabilizes in a year or two, the Swift runtime will
become part of the host OS and this limitation will no longer exist.
Until the Swift ABI (application binary interface) stabilises (I'm guessing another year or two) the only way to distribute libraries that will work across different Xcode versions is to distribute the source code. Cocoa pods and Carthage are both good tools for making library distribution easier but for Swift code they will still rely on source code being available.
It might be possible to have an Cocoapod that detects the version of Xcode it is run with and then downloads and provides the correct build of your library but you will still need to build the libraries for all Xcode versions that you want to support and recompile every time Apple release a new Xcode but at least the user wouldn't need to download a new version manually.

Resources