Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sharing swift code over multiple projects

So we have a few projects that share code, and they have to remain compatible to at least iOS7 for now.

Currently we use local cocoapods to share code between different applications. This has the downside that all shared code is being put in one group. Furthermore, the Cocoapods team explained why swift pods will not be available to iOS7 projects:

CocoaPods only supports Swift on OS X 10.9 and newer, and iOS 8 and newer.

Here's why:

Swift is supported on OS X 10.9 / iOS 7 and newer, as stated by Apple numerous times. There is no support for building static archives with Swift. Dynamic frameworks are supported on all versions of OS X. Dynamic frameworks are unsupported on iOS versions prior to 8:

ld: warning: embedded dylibs/frameworks only run on iOS 8 or later.

(Source: http://blog.cocoapods.org/Pod-Authors-Guide-to-CocoaPods-Frameworks/)

Given this information, we want to try and share the code using a Cocoa Touch Framework-project.

What I did was:

  • In the workspace, create a new project -> Cocoa Touch Framework
  • Add/Move swift code here and define needed functions/etc as public
  • In the main build target, add the new project as an "Embedded Framework"
  • Where you need to use classes from the defined library, use an import statement where the build target name is the module name (in my case import Cobra)

This seems to work, also on iOS7. Which is strange because everywhere online I read this warning makes sure the app won't run on iOS7 devices:

embedded dylibs/frameworks only run on iOS 8 or later

However, for us it seems to work fine on our iOS 7 testing devices. Furthermore, this concerns me:

enter image description here

The frameworks path seems directly link against my local DerivedData folder. I didn't specifically choose my DerivedData folder, I just added the suggested framework from within Xcode, and it decided by itself to grab it from my DerivedData folder. We work on this project with multiple programmers.

TL;DR;

Before I go down this path and move code to this new setup:

  • Wil this way of embedding a shared library cause problems for my team? (in other words: am I doing something wrong?)
  • Will this way of embedding libraries cause any problems when submitting the app to the App Store?
  • If needed: is there any alternative to way to share the code between the projects without simply copying code/files back and forth? I can't believe nobody else has this problem.
like image 754
Kevin R Avatar asked Feb 24 '15 10:02

Kevin R


1 Answers

Update 02-03-2015:

In order to share code internally, I recommend using git submodules, which require that you commit your code in a hosted repository, which can be either public or private.


Git Submodules

This is a way to distribute code stored in a repository to anyone with access. It has the benefit that you can push changes to the repository, which other consumers can then choose to update their own submodule repositories. It requires Git to be used as the project's source control and also requires the code to be pushed to a repository that the consumers have access to.

To use the code as a git submodule, you add the repository of the code to your git controlled project using the command:

git submodule add https://github.com/user/submoduleProject

replacing https://github.com/user/submoduleProject with your own repository URL.

Once this has been added you can then use the commands of:

git submodule init

and

git submodule update

to pull the code from the repository into the users workspace.

If you want to add any changes or updates to the submodule, you can do this and push it to the repository. Users can then update their code using git submodule update to obtain the latest changes.

More information on git submodules can be found at the official documentation

I hope this helps.


The app will not be accepted by Application Loader or Xcode when submitting to the App Store if a dynamic framework is used on an app that supports anything less than iOS 8. This is unfortunate because, as you said, it does work for iOS 7 when testing on a device.

The best way I can think of for you to share your code with your team is to hand over a folder of the code and include it in the project rather than including a dynamic framework. If you wish to keep the name spacing consistent so that in the future you can use the dynamic framework and migrate away from iOS 7, I recommend using an struct around the public methods and classes to obtain the namespace. For example:

public struct MyFrameworkName {
    public func doSomethingAmazing() {
         // Code...
    }

    public class DecentClass: NSObject {
         // Code..
    }

    public var terribleString: String
}

This will allow you to call the methods inside of the rest of the Application in the same way as with a Dynamic Framework

var myObject = MyFrameworkName.DecentClass()
myObject.doMethod()

MyFrameworkName.doSomethingAwesome()

MyFrameworkName.terribleString = "HEY";

In answer to your concern about linking to the framework directly from the derived data directory, this is generally an incorrect approach.

Ideally, you'd copy the framework into the project directory and then link against that version. This allows you to distribute the project's source directory to other people and the framework will remain at the correct location, relative to the project's source folder.

I hope this helps answer your question.

like image 138
Elliott Minns Avatar answered Sep 27 '22 17:09

Elliott Minns