こんにちは。メドピアのエンジニアの保立です。
メドピアでは、医師専用コミュニティサイト「MedPeer」のiOSアプリを3月26日にリリースしました。
詳しくはこちら
メドピアのiOSアプリは、swift4.0で開発を始めましたが、先日swift4.1にバージョンアップしたので、今回のブログ記事では、swiftのアップグレードのためにやったことについて紹介します。
swift4.0から4.1の変更点
3月29日にswift4.1がリリースされました。変更内容とメドピアでの対応について記載します。
変更1) SE-0157 Support recursive constraints on associated types (関連する型の再帰的制約をサポート)
変更内容
swift4.0以前では、「プロトコル内で、プロトコル自身を再帰的に参照する」ことを制限していましたが、swift4.1以降では、その制限が解除されました。
// swift4.0以前では、コンパイルエラーとなるprotocolSequence { // `SubSequence` が、再帰的に `Sequence` を参照しているassociatedtype SubSequence:Sequencewhere Iterator.Element == SubSequence.Iterator.Element, SubSequence.SubSequence == SubSequence funcdropFirst(_ n:Int) ->Self.SubSequence { ... } }
ちなみに、swift4.0以前では以下のように実装する必要がありました。わかりづらい。。。
protocolSequence { associatedtype SubSequence funcdropFirst(_ n:Int) ->Self.SubSequence { ... } } structSequenceOfInts:Sequence { funcdropFirst(_ n:Int) ->SimpleSubSequence<Int> { ... } } structSimpleSubSequence<Element>:Sequence { typealiasSubSequence= SimpleSubSequence<Element>typealiasIterator.Element= Element }
対応
プロトコル内でassociatedtype
を使って再帰的に参照している箇所を修正。
変更2) SE-0185 Synthesizing Equatable and Hashable conformance (EquatableとHashable適合性の合成)
swift4.1化のメインで、最もメリットを享受できる変更だと思います。
変更内容
Equatable
/ Hashable
プロトコル内に実装する必要があった決まり文句を、暗黙的に実装してくれるようになりました。
structQuestion:Equatable { letid:Int64lettitle:String// swift4.1以降では、 '=='の実装が不要になる。便利!publicstaticfunc== (lhs:Question, rhs:Question) ->Bool { return lhs.id == rhs.id && lhs.title == rhs.title } }
今までは、public static func == (lhs: Element, rhs: Element) -> Bool { ... }
を明示する必要があったため、プロパティの追加、削除、または変更があった場合、この演算子を更新しなければならないことと、手作業で記述する必要があるため、漏れや誤植で間違ってしまう可能性がありました。Hashable
の場合、以下のようになります。
structForumTag:Hashable { letid:Int64letname:String// swift4.1以降では、 '=='も 'var hashValue: Int{} ` も実装が不要になる。超便利!!varhashValue:Int { return id.hashValue } staticfunc== (lhs:ForumTag, rhs:ForumTag) ->Bool { return lhs.id == rhs.id } }
対応
Equatable
/ Hashable
プロトコルに実装された ==
や hashValue
を使うように修正。
変更3) SE-0187 Introduce Sequence.compactMap(_:) (Sequence.compactMap(_:)の導入)
変更内容
Sequence.flatMap
を廃止し、 同じ機能として、 compactMap(_:)
を導入する。
対応
コンパイルエラーになったら対応。(MedPeerアプリでは Sequence.flatMap
を使っている箇所はありませんでした)
変更4) SE-0188 Make Standard Library Index Types Hashable (標準ライブラリのインデックス型をHashableに)
変更内容
swift4から KeyPath
という機能が実装されました。
KeyPath
については Qiitaが参考になると思います。
対応
MedPeerアプリでは、KeyPath使ってないので対応不要。
(おまけ) SE-0143 Conditional Conformance (条件付き適合)
この変更は、swift4.2以降で実装されます。
変更内容
URL: https://github.com/apple/swift-evolution/blob/master/proposals/0143-conditional-conformances.md
型引数が特定の要件を満たす場合にのみ、ジェネリック型が特定のプロトコルに準拠するという概念を表現できるようにします。
例えば、Array
に対して、その要素がEquatableである場合に、Equatableプロトコルを実装することができることを表したい時、以下のように実装します。
extensionArray:Equatablewhere Element:Equatable { staticfunc==(lhs:Array<Element>, rhs:Array<Element>) ->Bool { ... } }
swift4.1以前で、上記のような実装をすると、「 'Array'自体がEquatableでない」という理由で、コンパイルエラーになります。
error: extension of type 'Array' with constraints cannot have an inheritance clause extension Array: Equatable where Element: Equatable { } ^ ~~~~~~~~~
これが解決されます。
Standard Library Adoptionに記載されている通り、 Optional
や Array
の Encodable
/ Hashable
適合など、既存のライブラリにはすでに内部で使われています。
swift4.1に移行する時につまづいたこと
swift4.1への移行はほぼスムーズにできましたが、1点だけ修正が面倒なことがありました。Firebaseなどのサードパーティーツールで、以下のようなWarningが出ることです。
/path-to-app/vendor/FirebaseCoreDiagnostics.framework/FirebaseCoreDiagnostics: Failed to parse executable: Unknown header: 1918975009
メドピアでは、ライブラリ管理にCarthageを使っていたのですが、FirebaseなどはCocoaPodsにのみ対応していたので、FirebaseSDKを直接ダウンロードしていました。それにより、Firebaseのバージョン管理が適切にできていないのが原因でした。
結局、Carthageで管理できないライブラリは、CocoaPodsで管理することで解決しました。
この修正により、以下のライブラリをCocoaPodsで管理するように修正しています。
- Firebase/Core - Fabric - Crashlytics - Repro - R.swift
まとめ
今回、メドピアでは初めてswiftのバージョンアップを実施しましたが、今後もバージョンアップ等で得た知見をブログに執筆していきます。
iOSアプリはまだリリースしたばかりで、開発したいこと/すべきことが山ほどあるので、メドピアに少しでも興味を持っていただけたら遊びに来てほしいです。
是非読者になってください(ง `ω´)ง
メドピアでは一緒に働く仲間を募集しています。 ご応募をお待ちしております!
■募集ポジションはこちら
https://medpeer.co.jp/recruit/entry/
■開発環境はこちら