LoginSignup
21
18

More than 5 years have passed since last update.

SwiftのライブラリをiOS 7で使うためにダミーのFrameworkを作ってimportをごまかす

Last updated at Posted at 2016-06-03

前置き

最近のオープンソースなSwift製ライブラリは、Embedded Frameworkとして使うことを前提としているものが多いです。それらをiOS 7対象のプロジェクトで使う場合にはソースコードを直接取り込むしか方法がないのですが、他のライブラリに依存しているライブラリは、コード中にimport DependentLibraryDependentLibrary.SomeClassなどと出てくるので、そのままでは使うことができません。

RxSwiftをiOS 7で使う」のようにプロジェクトに直接取り込む方法を用意しているライブラリはそれを使います。そうでないライブラリの場合はソースコードの改変が必要になります。しかし、importだけならソースコードを改変せずにごまかすことができるんじゃないかと思いました。

要するに、例えばimport DependentLibraryと書かれていたら、ダミーのDependentLibrary.frameworkを作ってあげればよいのです。そして、そのFrameworkは「Static Framework」としてビルドして、iOS 7でも使えるようにします。実際のソースコードは直接取り込みつつ、同じ名前のFrameworkを用意することで、importをごまかすわけです。

例:APIKitを改変せずにiOS 7で使う

というわけで、例としてResultに依存しているSwift製ライブラリであるAPIKitを、ソースコードの改変なしにiOS 7で動かしてみます。

1. APIKitとResultのソースコードをプロジェクトに追加する

APIKitResultをチェックアウトして、含まれているソースコードをすべて自身のプロジェクトに追加します。ただし、APIKitのFormURLEncodedDataParser.swiftだけはiOS 8以上でないとビルドできないので外します。

2. Bridging HeaderにAPIKit.hを追加する

APIKitはワークアラウンドのために一部Objective-Cで書かれているので、Bridging HeaderにAPIKit.hを追加します。前回を参考にしてください。

3. Resultという名前のターゲットを追加する

ここが肝です。APIKitのソースコード中のimport Resultをごまかすために、Resultという名前のStatic Frameworkを作ります。

昔はStatic Frameworkを作るには、まずStatic Libraryを作って、他のファイルも作って、フォルダ構成を整えて、と面倒だったのですが、いまはテンプレートが用意されているので簡単にできます。

まず、プロジェクトに新しいターゲットを追加して、テンプレートから「Cocoa Touch Framework」を選びます。名前をResultに、言語を「Objective-C」にします。Embedded Frameworkとしては使わないので、「Embed in Application」は「None」にしておきます。

Screen Shot 2016-06-03 at 16.36.45.png

Screen Shot 2016-06-03 at 16.37.06.png

このままではDynamic Frameworkになってしまうので、「Linking > Mach-O Type」を「Dynamic Library」から「Static Library」にします。iOS 7で使うので「Deployment Target」も7.0にします。

Screen Shot 2016-06-03 at 16.37.57.png

4. ダミーのResult.frameworkをターゲットに追加します。

APIKitを使いたいターゲットに、今回作ったダミーのResult.frameworkを含めるようにします。Dynamic Frameworkではないので「Linked Frameworks and Libraries」のほうに追加します。

Screen Shot 2016-06-03 at 16.50.07.png

5. APIKitを使ったコードを書いてiOS 7で動かしてみる

ここまでやるとビルドも通るようになり、iOS 7対象のプロジェクトでもAPIKitが使えるようになっているはずです。Demo.playgroundのGitHub APIの例などで試してみてください。

サンプルプロジェクト https://github.com/bricklife/APIKit-iOS7

ダミーのFrameworkでは解決しないケース

中身が何も入っていないFrameworkなので、Frameworkの名前空間や一部のインポートには対応できません。

例えば、ReactiveCocoaの以下の部分などが、Frameworkの名前空間に依存しています。public typealias Observer = Observer<Value, Error>とするとビルドできないので、どちらかの名前を変えざるを得ないと思います。

ReactiveCocoa/Swift/Signal.swift
    public typealias Observer = ReactiveCocoa.Observer<Value, Error>

また、同じくReactiveCocoaの以下の部分などで、Frameworkの一部をimportしているのですが、これも対応できません。

ReactiveCocoa/Swift/FoundationExtensions.swift
import enum Result.NoError

まとめ

手段が目的と化している感じがしますが、ライブラリのソースコードを改変しなければアップデートに追従する手間が格段に違うので、まだiOS 7をターゲットにしているプロジェクトを担当している方はぜひ試してみてください!

21
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
18