This entry is for Japanese speaker. Those who are interested to contribute R.swift, please refer to this doc
これはiOS Advent Calendar 2016の12/3の記事です。
Swiftでprintlnを書いてハマるレベルのエンジニアが一週間(実稼働時間 約8時間)でR.swiftにコントリビュートしたお話。(だったけど、メンテナさんが別プロジェクト始めちゃってまだマージされていない。-> この記事の翌日2016/12/04にマージされましたー!)
Swift開発している人にとっては常識な話が多数だと思いますが、Android開発やKotlin触っていて、Swiftもやってみたい!とかSwiftのライブラリ開発してみたい!という人向けです。R.swiftのコントリビュート方法として紹介していますが、他のライブラリも同じ感じなのではないかなーと思ってます。
想定読者
- Android開発やKotlin触っていいて、iOSの開発も興味がある
- Swiftのライブラリにコントリビュートしてみたいけど、したことがない
申し訳ないですが、iOS/Swift開発経験が長い人は想定外です。
自己紹介
Kotlinが好きなAndroidエンジニアです。
- Swift力: printlnとか書いて、コンパイルエラーになって、なんでや?って悩むくらい
- Xcode力: 新規ファイル作成は任せろ!
- その他: cocoapodは知ってた。ObjCは書いたことあったけど、ブランクが2年ほどある。
iOS開発は素人に毛が生えた程度のレベルの人間ということです。
経緯
- Swift3の勉強したい。
- あ、そういえば、こんな記事が・・・
- やるか!
プロジェクト選定
プルリク駆動開発のルールは以下です。
- GitHubのスターが500以上。出来れば5000以上
- 開発が活発
- Issueがラベルなどで管理されている
- 放置されているpull requestが少ない
- GitHubで完結している
- 使ったことあるなしは気にしない
これに則って、勉強できそうな星多いライブラリを探してみました。
名前 | ライブラリ概要 | 検討した理由 | 検討結果 |
---|---|---|---|
Himotoki | タイプセーフなJSONデコードライブラリ | メンテナーが日本人のikesyoさんという安心感から。 (恐れ多くて関わったことがないのですが・・・) |
issueなし!(スゲェ・・・ |
Kingfisher | Imageのダウンロード・キャッシングライブラリ | なんか名前がかっこよかった | 開発活発○ ラベリングがない☓ |
Alamofire | Swift版HTTPネットワーク | Swiftやるならこれでしょという短絡的な発想 | 開発活発○ ラベリングあり○ メインテナー多そう○ HTTP周りの知識必須っぽい△ |
R.swift | コンパイルタイムでコード生成 Androidで言うRクラスを使えるようにするライブラリ |
自分がAndroid出身者だから | 開発活発○ ラベリングがしっかり○ メインテナーが複数いるっぽい○ 自分が持っている知識でいけるっぽい○ |
ということで今回はR.swiftを選択しました。
実際に勉強出来た事
今回のコントリビュートで以下の項目を勉強しました。
- ライブラリのビルド方法
- サンプルアプリのビルド方法
- Swiftの文法(optional/guard/コレクション処理など)
- Cライブラリ/Cコードの導入方法
- リフレクション?(Mirror)
- XCTestの書き方
なかなか濃い一週間でした。
ライブラリのビルド方法
ここをrswiftに変える。
Runではなく、BuildでOK
サンプルアプリのビルド方法
ここをResourceAppに変える。
ライブラリのコード内にprint()
を書けばrswift.log
というところにログが出力されるように設定されています。これを利用して、変更を確認していきます。
Swiftの文法
自分は本を読んで勉強するというタイプではなく、try-errorで実際に触って勉強するタイプです。
Swiftの文法も書きながら覚えていきましたが、ちょくちょくこれどうやればいいの?っていうのにぶつかりました。特にKotlinのsmartcastの知識が邪魔してきました。。。if let guard
などは文法が結構特殊なので最後まで慣れませんでした。あと、一番の問題はSwift3を調べたいのですが、大量にSwift2などの古い日本語ドキュメントが出てきます。iOS開発者辛いなーという感じでした。OptionalもコンセプトはKotlinと似ているのですが・・・。この辺りでKotlinとSwiftが似ていると言っていた人を罵りたくなってました。
コレクション処理に関してはRubyやJava8、Kotlinなど他の言語でもよくあるものなので、そこまで苦しまなかったです。
Cライブラリ/Cコードの導入方法
残念ながら今回採用はしなかったのですが、Cコードの導入を試みました。
Androidであれば、NDKを入れて、Cコードとjnlを用意してーと本当に多くのことをやらないとCコードを利用することは出来ません。iOS開発のこれは強みで、比較的簡単に利用出来ます。
導入方法としては
- .h/.cファイルをプロジェクトに追加します。今回は
wildmatch.h
/wildmatch.c
- rswift-Bridging-Header.hファイルを作成し、利用したい.hをimportします。
#import "wildmatch.h"
- Swiftで
wildmatch.h
にあるメソッドを呼び出します
こんなことで利用出来てしまうんか!と驚愕しました。Xcodeのコンテントアシストにも即時反映されるし、驚きっぱなしでした。
リフレクション?(Mirror)
SwiftにもJavaのリフレクションがありました。Mirror
というクラスを利用します。実はこれ使い方が間違っていたのかうまく動きませんでした。
1 2 |
|
ちなみにこのコードであれば動きます。
1 2 |
|
たぶんselfとかのせいだろうなーと思いましたが、深追いはせず。
XCTestの書き方
ざっくりですが、JUnit3とほぼ同じです。
setup
/tearDown
メソッドが存在しているtest
prefixをそれぞれのテストメソッドにつける
BuildしたところにTestという選択肢があるので、それを選らんで実行。Java開発に慣れているなら特に問題なかったです。
ある程度開発した後に気づいたので、今回は利用しなかったのですが、XCTestでのTDD開発も可能です。たぶんそちらのほうが推奨されているのではないでしょうか。
苦戦したところ
メンテナさんにも指摘を受けたのですが、やっぱりところどころSwiftらしくない書き方をしてしまっているようです。たぶんKotlinの癖が出ているのではないかと。まだSwift力が低すぎてどこのことを言っているのか不明でした。
また、Swiftのif let
やguard
には結構苦戦しました。例えば今回こんな感じで、ignoreFile
という変数を初期化するコードを書きました。
1 2 3 4 5 |
|
let rswiftignoreURL
が
1 2 3 |
|
このスコープ内で使えることに違和感がありました。
Kotlinの場合は?.let
を利用した場合、lambdaの{}
内で変数定義します。(上記Swiftコードはelse
もあるので再現するには、?.let
ではだめだけど。あとit
もあるけど、それは省略。)
1 2 3 |
|
最後に
メインテナさんがPR投げてから、昇華していこうぜスタイルの自分にとって理想的な人でした。彼?のおかげで、わかる点までやってみて結果を貼って、質問するスタイルで勉強しつつコードを完成させることが出来ました。
みんな使ってね!