Deployment Target 7.0 での Swift 開発

(追記)

コメントにも書いてある通り、よくよく調べてみるとビルドはできるが、申請は無理らしい

> In the meantime, I will point out that it is only supported to use an embedded framework on iOS 8. The only question is whether you could use dlopen() to conditionally load the embedded framework on iOS 8, and not load the embedded framework on earlier versions of iOS.

http://stackoverflow.com/questions/29682272/embedded-frameworks-ios-8/29982816#29982816

# 前置き

iPhone ユーザーは OS のアップデートに対して積極的に取り組んでくれるが、まだまだ レガシー OS に対して対応しなければならないことがあると思う。

しかし、Deployment Target 7.0 での Swift の開発は非常に厄介で、**CocoaPods による Swift ライブラリの導入ができない**。そこでライブラリのソースファイルをプロジェクトにドラッグアンドドロップで入れるというお粗末な導入がしばしば見受けられる。これによる弊害として

- 名前空間が使えない
- バージョン管理下にライブラリのソースコードが入る（submoduleで解決するが...）

特に名前空間を使えないのは、非常に困る。Swift の名前空間は C++ のような明示的なものではなく Embedded Framework 単位で名前空間 [^1] が分かれている。そのため、同じターゲットに対してドラッグアンドドロップで Swift のライブラリを追加していくと、まれにクラス名が被ってコンパイルできないことがある。Carthage [^2] を使うなど対応方法があるが、多くのライブラリが CocoaPods を使用しているという状況。

そこで、自分の環境では **Embedded Framework** と **git submodule** を利用して名前空間を利用しながら Swift で iOS の開発をしているのでその紹介をする。

# 手法

## 構成

CocoaPods (Obj-Cのライブラリのみ使用)を利用した環境を想定する。
ここに`./Vendor`と`./Vendor/Checkouts`というディレクトリを作成しておく。

```
➜ tree -L 1
.
├── Deploy7Sample
├── Deploy7Sample.xcodeproj
├── Deploy7Sample.xcworkspace
├── Deploy7SampleTests
├── Podfile
├── Podfile.lock
├── Pods
└── Vendor
    └── Checkouts

6 directories, 2 files
```

## 手順

[Alamofire](git@github.com:Alamofire/Alamofire.git) を導入してみる。まずは submodule で `./Vendor/Checkouts` に checkout

```
➜ git submodule add git@github.com:Alamofire/Alamofire.git Vendor/Checkouts/Alamofire
Cloning into 'Vendor/Checkouts/Alamofire'...
remote: Counting objects: 1741, done.
remote: Compressing objects: 100% (52/52), done.
remote: Total 1741 (delta 23), reused 0 (delta 0), pack-reused 1689
Receiving objects: 100% (1741/1741), 930.78 KiB | 744.00 KiB/s, done.
Resolving deltas: 100% (982/982), done.
Checking connectivity... done.
```

次にプロジェクトを開く

```
➜ open Deploy7Sample.xcworkspace
```

まずは **File** -> **New** -> **Target** から **Cocoa Touch Framework** を選択

![スクリーンショット 2015-06-23 15.57.55.png](https://qiita-image-store.s3.amazonaws.com/0/42035/15f5ed2b-21c0-82d7-31d8-ea4966532fd5.png)

![スクリーンショット 2015-06-23 16.17.17.png](https://qiita-image-store.s3.amazonaws.com/0/42035/17234b57-2ff9-f734-2e2c-661971285785.png)

Framework の名前は **Alamofire** にしておく

![スクリーンショット 2015-06-23 15.59.24.png](https://qiita-image-store.s3.amazonaws.com/0/42035/66088b8f-33fc-8553-f14d-73f5b1ef91a8.png)

すると `Alamofire` と `AlamofireTests` というターゲットとグループができるので Unit Test の AlamofireTests どっちも使わないので消しておく。

![スクリーンショット_2015-06-23_15_59_42.png](https://qiita-image-store.s3.amazonaws.com/0/42035/dc31be4c-5cf7-4371-a302-c2680f870b6e.png)


`./Alamofire`ディレクトリは`./Vendor`の中に移動し、

```
mv Alamofire Vendor/Alamofire
```
グループ`Vendor`とその子供にグループ`Alamofire`を追加する。

![スクリーンショット 2015-06-23 16.01.44.png](https://qiita-image-store.s3.amazonaws.com/0/42035/daf65e08-ef22-6150-8201-523082481a4a.png)


このままだとグループとディレクトリ構成が合わないので、グループ`Vendor`と`Alamofire`のロケーションを変更しておく。

- グループ`Vendor` -> `./Vendor`
- グループ`Vendor/Alamofire` -> `./Vendor/Alamofire`

にロケーションを変更

![スクリーンショット_2015-06-23_16_01_54.png](https://qiita-image-store.s3.amazonaws.com/0/42035/1c520c25-6add-db8c-b0ca-13db30b95bcc.png)

![スクリーンショット 2015-06-23 16.03.53.png](https://qiita-image-store.s3.amazonaws.com/0/42035/0fc5b738-e0d5-8333-9cbd-b5153e8e59b2.png)

グループ`Alamofire`を移動させると`info.plist`が行方不明になるので、`info.plist`をダイアログから選択しておく。

![スクリーンショット 2015-06-23 16.04.24.png](https://qiita-image-store.s3.amazonaws.com/0/42035/2554dc4c-bc33-951b-5ac6-0d30d055a290.png)

Alamofireのソースファイルをプロジェクトに追加する。
**この時に`Copy items if needed`のチェックを外しておくことと`Add to targets`のチェックを`Alamofire`に変更しておくことを忘れずに**

![スクリーンショット 2015-06-23 16.07.58.png](https://qiita-image-store.s3.amazonaws.com/0/42035/f172f62f-bc9b-5d24-760d-6c4bbe5a0ca3.png)

![スクリーンショット 2015-06-23 16.08.17.png](https://qiita-image-store.s3.amazonaws.com/0/42035/abc02c4b-7950-1ff1-041e-df94b9dea397.png)

Deployment Target を 7.0 に設定する

![Untitled.png](https://qiita-image-store.s3.amazonaws.com/0/42035/96bd23c3-882c-bd78-ac5f-085cf4e9a395.png)

あとは`ViewController`に次のサンプルコードを書いて終了

```swift
import UIKit
import Alamofire

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        Alamofire.request(.GET, "http://httpbin.org/get")
            .response { (request, response, data, error) in
                println(request)
                println(response)
                println(error)
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}
```

![スクリーンショット 2015-06-23 16.10.32.png](https://qiita-image-store.s3.amazonaws.com/0/42035/dcdffdef-245b-7f11-4dd9-90909d8c2d80.png)


## 参考URL

- [[Xcode6] SwiftでCocoa Touch Frameworkを作る](http://mushikago.com/i/?p=5521)


[^1]: [Swiftの名前空間とは](http://tsuchikazu.net/swift_namespace/)
[^2]: [https://github.com/Carthage/Carthage](http://qiita.com/susieyy/items/4222989485e16e7eb53e)