Objective-CでFrameworkを作りSwiftからimportする

iosobjective-cswift

Frameworkの作成

New -> ProjectでFrameworkをLanguage Objective-Cで作成。

最低限の実装とHeaderを書いた。このHeaderはBuild PhasesのHeadersにPublicとして登録されている。

  • TestObjcFramework.m
#import <Foundation/Foundation.h>

void hello() {
    NSLog(@"hello");
};
  • TestObjcFramework.h
#import <UIKit/UIKit.h>

//! Project version number for TestObjcFramework.
FOUNDATION_EXPORT double TestObjcFrameworkVersionNumber;

//! Project version string for TestObjcFramework.
FOUNDATION_EXPORT const unsigned char TestObjcFrameworkVersionString[];

// In this header, you should import all the public headers of your framework using statements like #import <TestObjcFramework/PublicHeader.h>

void hello(void);

arm64(実機)/x86_64(Simulator)両方で使えるUniversal Frameworkをビルドするため、 New -> TargetでAggregateを作成し、Build PhasesのNew Run Script Phaseで、 各環境でxcodebuildしてlipoでUniversal Binaryにする次のスクリプトを追加する。

https://gist.github.com/cromandini/1a9c4aeab27ca84f5d79#file-universal-framework-sh

Build Phases

Targetを追加したAggregateにしてビルドするとFrameworkができる。 Frameworkはライブラリを内包したディレクトリ。

$ tree TestObjcFramework.framework/
TestObjcFramework.framework/
├── Headers
│   └── TestObjcFramework.h
├── Info.plist
├── Modules
│   └── module.modulemap
├── TestObjcFramework
└── _CodeSignature
    └── CodeResources

Swiftからimport

適当にSingle View Appを作成。FrameworkをProjectのディレクトリ直下に置き、Dynamic frameworkなのでEmebedded BinariesにFrameworkを追加。 ビルド時に見つからなかったらBuild SettingsのFramework Search Pathsに$(PROJECT_DIR)が含まれていることを確認する。

import UIKit
import TestObjcFramework

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        hello()
    }
}

通常Framework名と同名のHeaderがあるので誤解していたが、importのところに書くのはimportしたいHeader名ではなくFramework名。 Modules/module.modulemapにumbrella headerが書かれていて、これが読まれる。

framework module TestObjcFramework {
  umbrella header "TestObjcFramework.h"

  export *
  module * { export * }
}