Swift の Embedded Framework と namespace

Embedded Frameworkを、Swiftで作ると、Objective-Cで作るときとは違った利点がいろいろと見えてきました。

SwiftによるEmbedded Framework

Embedded Framework in Objective-Cのエントリで、Objective-CによるEmbedded Frameworkを実装してみましたが、SwiftによるEmbedded Frameworkはどうなるでしょうか。

ここでは、newsという名前のアプリにotheranimalsというEmbedded Frameworkをいれてみることにします。 まずは、Swiftを選んでnewsアプリを作成。

newtarget

そのあと、アプリにEmbedded Framework用の新規ターゲットを追加。 「File」-「New」-「Target」を選ぶと、こんな画面が表示されるので、「Framework & Library」から「Cocoa Touch Framework」を選択します。

addtarget Embedded Frameworkにotheranimalsという名前をつけて追加してください。

commo 追加すると自動作成されるヘッダーファイル(otheranimals.h)は必要ないので、削除。

ここまでで otheranimals ライブラリができてメインのターゲットにリンクされた状態になりました。

ライブラリにクラスを追加

次は、ライブラリに自分の使うクラスを追加してみましょう。 (ファイルを追加するときには、メインのターゲットではなく、Embedded Frameworkに追加してください。)

ここでは、シンプルなCatクラスをつくってみます。 新規ファイルでSwiftを選んで、Catクラスをotheranimalsのターゲットに追加。 クラスやメソッドのアクセス指定子にはpublicをつけてください。

import Foundation

public class Cat{
    
    public init(){

    }
    
    public func meow(count: Int) -> String {
        
        println(" meow! \(count)")
        
        return "meow (otheranimals version)"
    }

}

そして、メインのnewsターゲットのViewControllerでotheranimalsをimportするとEmbedded Frameworkのクラスを使うことができます。

import otheranimals

class ViewController: UIViewController {

    override func viewDidLoad() {
        
        super.viewDidLoad()

        var cat1 : Cat = Cat()
        cat1.meow(3)
 
    }

SwiftのEmbedded Frameworkは、簡単に作ることができますよね。

namespace と Embedded Framework

さて、Objective-Cと違って、Swiftではnamespace(名前空間)が使える、というのが売りの一つになっていました。

namespaceは、関数や変数の名前が衝突することをふせぐための言語のしくみです。 もしこの仕組みがあると、AというFrameworkに既にlogというクラスがあっても、BというFrameworkでおなじlogというクラスを作ることができます。 Objective-Cではnamespaceが使えなかったため、クラス名に「UI」や「AF」などのprefixをつけて同じ名前にするのを避ける必要がありました。

Swiftでは、iOSの既存Framework(Module)単位がnamespaceになっています。 例えばUIImageはUIKitに含まれるクラスなので、「UIKit.」をprefixにつけてアクセスすることができますし、NSStringは同じように「Foundation.」をつけてアクセスすることができます。

        UIKit.UIImage;
        Foundation.NSString;

このModuleをつくる方法がEmbedded Frameworkというわけなんです。

namespace を使ってみる

では、ちょっとnamespaceをつかってみましょう。

例えば、上の例ではotheranimalsにCatというクラスがありますが、メインのnewsターゲットにもこんな感じで同名のクラスをつくってみましょう。

import Foundation

class Cat{
    
    init(){
        
    }
    
    func meow(count: Int) -> String {
        
        println(" にゃあ! \(count)")
        
        return "meow (otheranimals version)"
    }
    
}

これでotheranimalsとnewsの二つのターゲットにそれぞれCatができました。 そして、それぞれのCatはこんな感じでよんで試してみてください。

        var cat1 : Cat = Cat()
        cat1.meow(3)
        
        //OnionLibVersionNumber
        var cat2 : otheranimals.Cat = otheranimals.Cat()
        cat2.meow(5)

prefixをつけずに Cat()でよぶとnewsターゲットのCatがよばれ、otheranimals.Cat()でよぶとotheranimalsターゲットのCatがよばれます。

Swift の Embedded Framework の 対応バージョン

実は、SwiftでかいたEmbedded Frameworkは Deployment Targetを7.0にしてもそのままつかうことができます。

Objective-CでかいたFrameworkをiOS7で使うためには工夫がいりますが、Swiftだとそのまま使えるので、iOS7対応が必要であればSwiftの方が楽ですね。

まとめ

SwiftのEmbedded FrameworkはObjective-Cとは違う面が多く、もしかしてEmbedded FrameworkはSwiftを前提に開始されたのかもしれません。

SwiftでEmbedded Frameworkを使うと、namespaceをわけることができるので、大規模開発にむいていると言えそうです。