How to build a custom Swift framework and how is it related to the SPM? - swift

I am currently building code that I would really like to use as a framework by being able to import MyCustomFramework as I would with Apple frameworks (in the future I would also like to distribute them).
I have some questions about that :
What is the easiest way to build a framework as what I want? Is this possible to do it directly in Xcode or do I need to use command line tools in the Terminal?
Will this framework be compatible with multiple platforms (I am thinking about all Apple platforms but also about other platforms supported by Swift such as Linux).
What is exactly the link between Swift frameworks and the Swift Package Manager ? Do I need SPM to build my framework or is this two different tools?
Thank you.

Currently, Swift Package Manager (SPM) and Xcode Frameworks follow different paths. For Linux, you have to follow the SPM path since the only way to compile a Linux swift application is to use SPM. For macOS command line apps, you can follow the SPM path as well. For iOS apps and macOS UI apps, you have to follow the Xcode Frameworks path.
For the SPM path, you make the project of your framework SPM-enabled: add Package.swift file and set the file layout of your project according to SPM conventions. The project also has to be a git repository. Then the git repository of your project can be specified as a dependency to other SPM-enabled frameworks/applications. Each SPM-enabled project can be converted to an Xcode project any time by using swift package generate-xcodeproj command.
The Xcode Frameworks path is the standard, pre-SPM way of working with frameworks with Xcode, which is described elsewhere. You create an Xcode Project that will define your framework.
So, if you want your framework to be used both in SPM-enabled projects for Linux and macOS command line apps, and in Xcode-enabled projects for iOS and macOS UI apps, you have to follow the dual path. You make your project SPM-enabled and add an Xcode Project which will define your framework. You will have to maintain your project information twice - in Package.swift file and in the Xcode Project.

I gave a detailed answer on how to use Xcode to create a Framework target in an answer 2 weeks ago here. The question wasn't specifically related to Frameworks, so I can understand how it doesn't come up in a search. (I also believe if I copied/pasted it here that would be unwelcome, but if I'm wrong I'll do it.)
For now a Swift Framework target can be compatible across Apple platforms, provided you separate UIKit, Foundation, and core code into their own frameworks. (There may be a better way but that's the best way I know.
About Swift core code: Currently Swift is (still) evolving fast. Swift 3 is beginning to have production server-side use and some Linux use, but right now with no binary compatibility (that's part of Swift 4) I'd stick to Apple platforms.
I've heard conflicting things about Swift version compatibility between Swift 2 & 3. By this I mean you can use both in the same project, but there are hurdles if you do.

Related

Adding a Swift system library to an xcode project?

I have a small Swift library intended to import a c library for use in Swift.
I'd like to use that in a "hello world" Mac app I have built in Xcode. This seems like a very simple use-case, but I have not been able to figure out specific steps will let me include that swift library -- add to targets? import the library project into xcode? build as a framework and add? This feels very elementary, but I can't find an up-to-date how-to for Swift 5 and Xcode 10.2.

Firebase SDK (v2.5.0) in OSX framework

I'm trying to link to the Firebase SDK (v2.5.0) within my OS X framework, but it keeps telling me I am trying to link to a framework built for iOS.
It seems to state pretty clearly on the Firebase docs that the iOS framework can be used to build OS X clients as well, so does anyone know what I am doing wrong here?
ld: in /[...]/Firebase.framework/Firebase(Firebase.o), building for OSX, but linking in object file built for iOS, for architecture x86_64
As of 2.4.0 (changelog), Firebase no longer ships a single binary for iOS and OSX, but instead has multiple frameworks (Firebase.framework for iOS, FirebaseOSX.framework for OSX). Similarly, the iOS Cocoapod is named Firebase, while the OSX Cocoapod is named FirebaseOSX. This is due to several changes in our build process, such as adding bitcode support (which only makes sense on iOS).
We still build and release iOS and OSX through these channels, and continue to support OSX, though it's not heavily advertised (as you noticed). As mentioned, if you don't use Cocoapods, using https://cdn.firebase.com/ObjC/FirebasePlatform.framework-major.minor.patch.zip will get you the framework, then follow the Alternative Setup instructions for including it in your project.
You need to add some dependencies in your project's Build Phases:
libicucore.dylib
libc++.dylib
CFNetwork.framework
Security.framework
SystemConfiguration.framework
See the Apple docs on how to add these if you haven't done this before.
Ok, this is a bit weird.. But after digging around in the pod specs I noticed that the FirebaseOSX podspec links to a different url than the iOS pod (FirebaseOSX.framework and an older version).
So I decided to copy the framework url from the Firebase site, and change the name and try that, and it downloaded a OSX framework for me. This is really weird, because I can't for the life of me understand that I should do like that based on what I can read on the Firebase site, so I can't really consider this the official way as it doesn't really make any sense. But it seems to work for now..
So for v2.5.0 the url is:
https://cdn.firebase.com/ObjC/FirebaseOSX.framework-2.5.0.zip

Create a single iOS framework-file from ZXing QR reader project

I have been looking for 2 days now, trying to find a way to get a single iOS framework-file for the ZXing QR reader. The only thing i can find, is a ZXingWidget project to include in my own project. But here, i have to add path's, dependencies etc. for it to work.
Isn't there a way to create one single .framework file that can easily be added to any new projects needing this feature?
I have found a kstenerud iOS framework template to create frameworks, but i can't make it work with the ZXing project.
No, there's no good solution for this for iOS.
Frameworks are generally (always?) dynamically-linked libraries and Apple doesn't allow DLLs on iOS. Note that there are now framework builds for OS X.
It may be possible to hack Xcode to produce a framework with a statically linked library, but that's going against Apple's patterns which means I suspect it will push Xcode into corner cases which fail in subtle and hard to debug ways and which have a high chance of breaking across Xcode versions.
This opinion comes in part from talking to Apple Xcode engineers at WWDC about cleaning up the ZXing project files. There are new project files now that follow all the best practices they recommended but on iOS they still require the same include path and library linkage project customization that the old project files require.

When to use framework in Objective C development

Not many libraries such as GHUnit suggest you to use them as a Framework.
While most libraries such as Facebook iOS SDK just require you to drag the project into existing XCode project.
So when you are building a library which suppose to be re-use by other project in the future, should you use Framework or just like many current opensource projects, don't use Framework provided by XCode.
There is a reason why those opensource projects are provided as static libraries or just source code and not Framework, Frameworks are currently not supported by iOS SDK.
You can only use Frameworks provided by Apple - parts of SDK itself. Your code cannot be linked against your own or third party Frameworks.
So stick with one of those ways - I personally prefer static libraries.

Can I develop my own objective-C Framework for Cocoa Touch Applications?

Is it possible to create an own obj-C Cocoa Touch framework which can be used by other developers? And furthermore can you protect this framework?
I've created templates for Xcode 4 that allow you to build universal iOS frameworks (which work in both device and simulator).
Once the templates are installed, you simply select "Static iOS Framework" when creating a new project and it does the rest. It also works with unit tests.
https://github.com/kstenerud/iOS-Universal-Framework
You can create a static library. There is an option in the XCode project chooser to do this. You'll have to distribute the compiled static library file and the header files to users of your library. Your actual implementation files (.m) do not need to be distributed.
GHUnit does a good job of this - packaging up the libraries for both simulator and device - so I recommend looking at this project. (I also recommend using this library for unit testing :-)
The frameworks in Objective C are typically just C / ObjC code and a bunch of classes, nothing amazingly special. As such, you can create your own if you'd like, and then just include that in your project when you build it. The iPhone doesn't care about the difference, it just knows to put all that code into your app, along with everything else.
Have a look at the Framework Programming Guide on Apple's website. It will get you started. Essentially what you'll do is create a Framework project in XCode and then go from there.
As for "protecting" your framework, I assume you mean making your code unreadable. I'm not sure if and how you can do this, but perhaps Apple's guide will say something about it.
Yes you can create frameworks for use with Cocoa Touch.
However there are these caveats:
has to be a statically linked libary, no dynamic loading (dyld) for us
should be a combined (lipo) library for i386 (simulator), arm6 and arm7
you need to hack a bundle project into a framework
you should embed (small and few) images into the library so that the developer does not have to mess around with resources but just drags/drops it into his project
... or if you have large and many images build a bundle with these
I have guides for these things on my site.
1+2 = http://www.drobnik.com/touch/2010/04/universal-static-libraries/
The other links you have to google because this site does not let me post more than one URL.
You could make a static library available as binary (i.e. rudimentary "protection") to third parties, but not a dynamic one, as Apple's App Store policy prevents dynamic linking.
Take a look at a worked example for static libraries given at
this site
If you're going to do it, in my opinion JSON.framework is a great example to follow. To hide/obfuscate the source code is a different story, and a different question entirely,
When creating a new project, navigate to iOS > Framework & Library > Cocoa Touch Framework, it's as simple as that. When you are successfully compile, .framework will be created under Products folder in XCode. Right click to show in Finder, and you can find the output.
It's unlikely this will work the way you want it to because the other developers won't be able to use your framework. This StackOverflow Question explains why.