LoginSignup
6

More than 5 years have passed since last update.

複数OSに対応したSwift oss library作成チュートリアル

Last updated at Posted at 2018-08-24

はじめに

iOS,macOS両対応のSwiftライブラリを作りたいと思い立ったのですが,それってどうやって作れば良いのだろう。
今回はRxSwiftに依存したものを作りたかったので,RxBluetoothKitを紐解きつつ作成手順を記します。
結構長いので覚悟してついてきて下さい。

環境

  • macOS High Sierra 10.13.6
  • Xcode 9.4.1

本記事完了時点でのディレクトリ

2018/08/23現在のRxBluetoothKit masterの様子 -> 69c1d18
主要ディレクトリおよびファイルを抜粋したものです。ここまでを目指します。

ExampleApp/
 ├ ExampleApp.xcodeproj/
 ├ ExampleApp.xcworkspace/
 ├ ExampleApp/
 └ Podfile
RxBluetoothKit.xcodeproj/
Source/
Tests/
 └ Info.plist
docs/
 └ index.html
scripts/
 └ all-tests.sh
.gitignore
.jazzy.yaml
.swift-version
.swiftlint.yml
.travis.yml
Cartfile
Cartfile.private
Cartfile.resolved
LICENSE
Package.swift
README.md
RxBluetoothKit.podspec

ディレクトリの作成

最初にgitから作成します。今回は中~大規模を想定していますので,Git-flowを利用することにします。

$ mkdir <foo>
$ cd <foo>
$ git init
$ git flow init

ここまでのディレクトリ構成

以降は.gitは省略します。

.git

参考

ソースファイルの作成

Swift Package Managerを利用してプロジェクトを作成します。今回はライブラリ形式で作成するので,--type libraryのオプションを付けています。

$ swift package init --type library

ここまでのディレクトリ構成

Source/
 └ <foo>/
    └ test.swift
Tests/
 ├ <foo>Tests/
 │ ├ <foo>Tests.swift
 │ └ XCTestManifests.swift
 └ LinuxMain.swift
.gitignore
Package.swift
README.md

一気にそれっぽくなってきました。
この辺りで.gitignoreREADME.mdの整理をすると良いでしょう。LICENSEの追加をしても良いです。
LinuxMain.swift XCTestManifests.swift は不要なので削除します。

参考

xcodeproj の作成

$ swift build
$ swift package generate-xcodeproj

ここでようやくXcodeから開くことができるようになります。
Xcodeで開くとSourcesTestsが参照無しのGroup(Group without Folder)となっているのでここで直しておきましょう。

ss 2018-08-23 at 21.38.49.png

ここまでのディレクトリ構成

<foo>.xcodeproj/
Source/
 └ <foo>/
   └ test.swift
Tests/
 └ <foo>Tests/
   └ <foo>Tests.swift
.build/
.gitignore
LICENSE
Package.swift
README.md

参考

参考

TARGETの作成

Xcodeでの作業です。自動生成されたTARGETを削除し,必要なものを作成します。
今回はiOS (Cocoa Touch Framework) とmacOS (Cocoa Framework) を用意しました。

ss 2018-08-14 at 10.35.37 copy.png

ここでいくつかのファイルが自動生成されます。
OS毎に共通したInfo.plistがあれば良いので,Framework用とTest用で1つずつ用意します。テストファイルも共通化しましょう。それ以外のファイルは削除します。

Info.plistの移動

  • Framework用のInfo.plistの移動

Framework用のInfo.plistはSource以下に配置し,
一旦Remove Referenceで参照を破棄します。

ss 2018-08-23 at 21.40.21.png

その後Xcode上のプロジェクト直下でNew Group without FolderとしてSupporting Filesを作成し,Info.plistを参照します。

ss 2018-08-23 at 21.46.01.png

この時TARGETSのBuild Phases / Copy Bundle ResourcesにInfo.plistが存在すると正常にビルドできないため削除します。

ss 2018-08-23 at 21.46.39.png

ここで間違っている場合はTARGETSのIdentifyにChoose Info.plist File...が表示されています。選択して直してあげましょう。

ss 2018-08-23 at 22.04.15.png

  • Test用のInfo.plistの移動

こちらはそのままTests以下にTest用のInfo.plistを配置します。

しかし,テストの方はTARGETSのBuild Settings / Packaging / Info.plist Fileをマニュアルで変更する必要があります。

ss 2018-08-23 at 22.11.37.png

ここまでのディレクトリ構成

ss 2018-08-23 at 21.54.40.png

<foo>.xcodeproj/
Source/
 ├ <foo>/
 │ └ <foo>.swift
 └ Info.plist
Tests/
 ├ <foo>Tests/
 │ └ <foo>Tests.swift
 └ Info.plist
.build/
.gitignore
LICENSE
Package.swift
README.md

Schemeの設定

XcodeのTARGETSを変更したのでSchemeが崩れています。調整しましょう。
Manage Schemes...から不要なSchemeを削除し,残ったもののSharedにチェックを付けましょう。後にTravis CIで参照する際に必要となります。

ss 2018-08-23 at 22.01.28.png

ss 2018-08-23 at 22.02.23.png

TARGET Deviceの調整

ターゲットのデバイスも調整しましょう。現在はCocoa Touch Frameworkで作成してもSchemeには反映されていません。
変更したいTARGETのBuild Settings / Architectures / Supported Platformsを変更する必要があります。

ss 2018-08-23 at 22.16.56.png

ss 2018-08-23 at 22.21.08.png

Test実行

ここでビルドおよびテストを実行してみましょう。ビルドは通りますが,テストは通らないと思います。
原因はテスト共通化のために追加したTARGET名が@testable importと異なることで発生しています。修正しましょう。

FrameworkのTARGETのBuild Settings / Packaging / Product Nameを共通する名前に変更しましょう(TestのProduct Nameの変更は不要です)。
テストが通るかと思います。

ss 2018-08-23 at 22.33.22.png

参考

依存ライブラリの組み込み

Carthageを利用します。Homebrewは以後も利用しますので,利用していない方は【Swift】Carthage導入手順等を元に導入しましょう。

$ brew install carthage
$ touch Cartfile

Vim等で編集します。今回はRxSwiftに依存させます。

Cartfile
github "ReactiveX/RxSwift" ~> 4.0

インストールします。

$ carthage update

New Group without Folderを選択し,Frameworksという名で作成します。
Framework用にProject直下に1つ,Test用にTests/以下に1つ用意しましょう。
RxSwiftは各OS毎にBuild fileが分かれています。Frameworks以下にiOS macOSというGroup without Folderを作成しましょう。
RxSwiftではRxTest RxBlockingがテスト用ですので必要に応じて取り込みます。

ss 2018-08-23 at 23.57.10.png

ss 2018-08-24 at 0.03.36.png

適切に設定できた場合は以下のようにBuild Phases / Link Binary With Librariesに必要な分のみ参照されていると思います。

ss 2018-08-24 at 0.10.23.png

ここまでのディレクトリ構成

ss 2018-08-24 at 0.09.32.png

<foo>.xcodeproj/
Source/
 ├ <foo>/
 │ └ <foo>.swift
 └ Info.plist
Tests/
 ├ <foo>Tests/
 │ └ <foo>Tests.swift
 └ Info.plist
Carthage/
.build/
.gitignore
Cartfile
Cartfile.private
Cartfile.resolved
LICENSE
Package.swift
README.md

参考

サンプルアプリの作成

iOSサンプルを作成します。File / New / Project...からExampleAppという名のiOSプロジェクトを作成します。作成する場所はライブラリ直下 (.xcodeprojのある場所) です。

ss 2018-08-24 at 0.15.54.png

ss 2018-08-24 at 0.16.33.png

ここまでのディレクトリ構成

ExampleApp/
 ├ ExampleApp.xcodeproj/
 └ ExampleApp/
<foo>.xcodeproj/
Source/
 ├ <foo>/
 │ └ <foo>.swift
 └ Info.plist
Tests/
 ├ <foo>Tests/
 │ └ <foo>Tests.swift
 └ Info.plist
Carthage/
.build/
.gitignore
Cartfile
Cartfile.private
Cartfile.resolved
LICENSE
Package.swift
README.md

CocoaPodsの準備

$ pod spec create <foo>

設定等は自前のライブラリをCocoaPodsで管理するメモなどを参考に,登録方法は左記ではなくSwiftでライブラリを公開するを参考に。
サンプルアプリはCocoaPods登録後は通常のアプリ開発と同様です。

ここまでのディレクトリ構成

ExampleApp/
 ├ ExampleApp.xcodeproj/
 ├ ExampleApp.xcworkspace/
 ├ ExampleApp/
 └ Podfile
<foo>.xcodeproj/
Source/
 ├ <foo>/
 │ └ <foo>.swift
 └ Info.plist
Tests/
 ├ <foo>Tests/
 │ └ <foo>Tests.swift
 └ Info.plist
Carthage/
.build/
.gitignore
Cartfile
Cartfile.private
Cartfile.resolved
LICENSE
Package.swift
README.md
<foo>.podspec

参考

Swiftのバージョンを指定する

今回は4.0以上に設定します。.swift-versionを指定します。

$ echo 4.0 > .swift-version

ドキュメントの作成

Jazzyを利用します。Swiftソース上のドキュメントコメントからドキュメントを生成してくれるすごいやつです。

$ [sudo] gem install jazzy
$ touch .jazzy.yml

設定は[iOS][Swift] 「Jazzy」を使ってSwiftのソースファイルからドキュメントを生成する等を参考に。設定が完了したら以下のコマンドで生成できます。

$ jazzy -o docs

ここまでのディレクトリ構成

ExampleApp/
 ├ ExampleApp.xcodeproj/
 ├ ExampleApp.xcworkspace/
 ├ ExampleApp/
 └ Podfile
<foo>.xcodeproj/
Source/
 ├ <foo>/
 │ └ <foo>.swift
 └ Info.plist
Tests/
 ├ <foo>Tests/
 │ └ <foo>Tests.swift
 └ Info.plist
docs/
 └ index.html
Carthage/
.build/
.jazzy.yml
.swift-version
.gitignore
Cartfile
Cartfile.private
Cartfile.resolved
LICENSE
Package.swift
README.md
<foo>.podspec

参考

Linterの設定

realm/SwiftLint - GitHubを利用します。
.swiftlint.ymlを作成し,編集します。
日本語だとSwiftLintのRules全まとめ等を参考にしましょう。

$ brew install swiftlint
$ touch .swiftlint.yml

Xcode側ではrealm/SwiftLint - GitHubの説明の通りに
TARGETのBuild Phases左上のボタンより,New Run Scriptを選択して以下を入力して下さい。

if which swiftlint >/dev/null; then
  swiftlint
else
  echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint"
fi

ss 2018-08-24 at 10.38.42.png

ここまでのディレクトリ構成

ExampleApp/
 ├ ExampleApp.xcodeproj/
 ├ ExampleApp.xcworkspace/
 ├ ExampleApp/
 └ Podfile
<foo>.xcodeproj/
Source/
 ├ <foo>/
 │ └ <foo>.swift
 └ Info.plist
Tests/
 ├ <foo>Tests/
 │ └ <foo>Tests.swift
 └ Info.plist
docs/
 └ index.html
Carthage/
.build/
.jazzy.yml
.swift-version
.swiftlint.yml
.gitignore
Cartfile
Cartfile.private
Cartfile.resolved
LICENSE
Package.swift
README.md
<foo>.podspec

参考

CIの導入

Travis CIを利用します。OSSの範囲であれば無料で使えます。
GitHub連携後,.travis.ymlを作成します。設定はBuilding an Objective-C or Swift Projectを参考に。

$ touch .travis.yml

RxBluetoothKitではscriptにテストを書いているので参考に作成します。

$ mkdir scripts
$ touch ./scripts/all-tests.sh

ここまでのディレクトリ構成

ExampleApp/
 ├ ExampleApp.xcodeproj/
 ├ ExampleApp.xcworkspace/
 ├ ExampleApp/
 └ Podfile
<foo>.xcodeproj/
Source/
 ├ <foo>/
 │ └ <foo>.swift
 └ Info.plist
Tests/
 ├ <foo>Tests/
 │ └ <foo>Tests.swift
 └ Info.plist
docs/
 └ index.html
Carthage/
.build/
.jazzy.yml
.swift-version
.swiftlint.yml
.gitignore
.travis.yml
Cartfile
Cartfile.private
Cartfile.resolved
LICENSE
Package.swift
README.md
<foo>.podspec

参考

まとめ

ここでようやく終了です!お疲れさまでした!
でもここは終わりではなく始まりに過ぎません。
それでは皆様,良いOSSライフをお過ごし下さい!

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
6