LoginSignup
14
14

More than 5 years have passed since last update.

自作ライブラリをXcode8・Swift2.3/3.0対応する際にハマったこと

Last updated at Posted at 2016-10-04

まえおき

ふたつほど、マイクロライブラリを公開しています。

Notifwift: NSNotificationCenter wrapper for Swift
https://github.com/takasek/Notifwift

ActionClosurable: Extensions which helps to convert objc-style target/action to swifty closures
https://github.com/takasek/ActionClosurable

これらをSwift2.3/3.0に対応させていった手順を、記録に残しておきます。

どう対応するか

branch

ふたつ用意しましょう。

  • swift3.0用のbranch(masterでもいい)
  • swift2.3用のbranch

ユーザーがどちらのbranch(タグ)も選べるようにしておかないといけないので、必ず並行でbranchを稼働させるようにしましょう。

コーディング

Xcodeで自動的にmigrationできて、コンパイルが通ったからそれでOK…
だなんて、思ってませんか?

Migration Guideを読もう

Swift.org - Migrating to Swift 2.3 or Swift 3 from Swift 2.2

公式のドキュメントをしっかり読んで、適切な実装について理解しましょう。

Notifwiftでは、Notification名をこれまでString型で受けていたAPIを、 Notification.Name で受けるように変更しました。
後方互換性のためにStringのままにすることもできたのですが、あえて破壊的変更を選びました。
なぜなら、ガイドに次のような記述があったからです。

In Swift 3, many of Foundation’s “stringly-typed” APIs have been changed to use struct “wrapper types”, such as the new Notification.Name type. Since, it’s common for notification names and other string constants to be declared globally or as static members, the best way to take advantage of these new types is usually to construct the wrapper at the point of declaration:

static let MyGreatNotification = Notification.Name("MyGreatNotification")
// Use site (no change)
NotificationCenter.default().post(name: MyController.MyGreatNotification, object: self)'

アクセス修飾子もちゃんとしよう

これも、Xcodeの機械的なmigrationに任せるだけでなく、ちゃんと手を入れたい箇所。
Xcodeのmigrationに任せると、 public だった修飾子が open に変更されていまいます。
しかし、継承させたい意図がない場合はopenではなくpublicを使うべき。
同じく、その型の中でだけアクセスできればいいメンバについては、 fileprivate ではなく private を使いましょう。

ネーミングルールにこだわろう

Xcodeのmigrationでは、標準のAPIはmigrateできても、ライブラリのAPIはそのままです。
これをSwift3らしくリネームするかどうかは、あなた次第。
でも、かっこいいAPIにしたほうがいいんじゃないかなー。

Swift 3 その基本ルールを眺める #cswift
32ページ以降を読んでおくといいと思います
あるいはmono0926さんの
Swift API Design Guidelinesの紹介(Swift 3版) - Qiita

パッケージ管理対応

Carthage

何も罠がありませんでした。
素晴らしい。

CocoaPods

つらかったです。

CocoaPodsのバージョンは、 1.1.0 rc2 を使う

コマンドラインで案内が出てたので、深く考えずに以下を実行したのだけれど…
それだけだと使えませんでした。

CocoaPods 1.1.0.rc.2 is available.
To update use: `sudo gem install cocoapods --pre`

既にインストールされていたリリース版が優先されてしまったのです。

[Notifwift]@23:09 % pod --version
1.0.1

どうやればRC版を優先できるのか悩んだ結果…
"Quick and Dirty" なやり方に従うことにしました。

How to use different CocoaPods versions · Bitrise

[Notifwift]@23:41 % gem uninstall --all --executables cocoapods
ERROR:  While executing gem ... (Gem::InstallError)
    cocoapods is not installed in GEM_HOME, try:
    gem uninstall -i /Users/tksk_mba/.rvm/gems/ruby-2.2.1@global cocoapods
[Notifwift]@23:42 % gem uninstall -i /Users/tksk_mba/.rvm/gems/ruby-2.2.1@global cocoapods

Select gem to uninstall:
 1. cocoapods-1.0.1
 2. cocoapods-1.1.0.rc.2
 3. All versions
> 1
Successfully uninstalled cocoapods-1.0.1
[Notifwift]@23:42 % pod --version
1.1.0.rc.2

(2016/10/5追記)
@kishikawakatsumiさんからコメントいただきました。
http://qiita.com/takasek/items/c42641ca1ca03bb2ee39#comment-951c31b3b3b8d49ca985

CocoaPods(に限らずRubyGems一般)のバージョンを使い分けるのはBundlerを使うのが便利です。

詳しい使用法はコメントをご参照ください。

.swift-version を作る

CocoaPodsのtrunkは、そのライブラリのバージョンを判別する際に .swift-version というファイルの内容を参照するようです。

これはechoコマンドを使えば、手っ取り早く作れます。

echo "2.3" > .swift-version

あるいは

echo "3.0" > .swift-version

あとはいつもの手順

  1. 最新のbranchにtagつけて、
  2. pod lib lint して、
  3. pod trunk push
[Notifwift]@0:10 % pod lib lint                                                           (git)-[master]

 -> Notifwift (1.0.0)

Notifwift passed validation.
[Notifwift]@0:14 % pod trunk push                                                         (git)-[master]

[!] Found podspec `Notifwift.podspec`
Updating spec repo `master`
Validating podspec
 -> Notifwift (1.0.0)

Updating spec repo `master`
  - Data URL: https://raw.githubusercontent.com/CocoaPods/Specs/65608e550b0c28061345a403759ce7cd7a812863/Specs/Notifwift/1.0.0/Notifwift.podspec.json
  - Log messages:
    - September 23rd, 00:15: Push for `Notifwift 1.0.0' initiated.
    - September 23rd, 00:15: Push for `Notifwift 1.0.0' has been pushed (0.387305114 s).
[Notifwift]@0:16 %

Swift Package Manager

そんなに難しくないらしい?
余裕があれば。
自分は余裕なくなったので、またの機会にやります…。

すべて済んだら、

READMEをしっかり書こう

Swift2.3用branch、Swift3.0用branch、それぞれのREADMEに、最適化された形で次の情報があると親切です。

  • Swift2.2バージョンからのAPI変更点のまとめ、あるいはmigrationの手順
  • Cartfileに記述すべき内容
  • Podfileに記述すべき内容
  • Swift2.3用branchであれば、Swift3.0用branchへのリンク
  • Swift3.0用branchであれば、Swift2.3用branchへのリンク

以上であなたのライブラリのSwift2.3/3.0対応は完了です。
お疲れ様でした。

14
14
2

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
14
14