--> 2016/09/25追記
本家がSwift3に対応しました🎉
ご利用の際はぜひこちらを
Release Swift 3 Xcode 8 Support · SwiftyJSON/SwiftyJSON
(この記事よりもっとちゃんと綺麗に丁寧に直されてました:-P)
背景
iOSアプリを急遽Swift3化して審査に出さなくてはならなくなったのですが、アプリで使ってるSwiftyJSONがSwift3に対応していなかったのでSwift3化してみたメモ。
SwiftyJSONは現在(2016/9/16)swift3ブランチはあるもののcommitが3ヶ月前と古くてそのままでは使えず。またXcode8に対応したとするPRはあるものの、本当に使えるのかわからなかったので取り急ぎ自分でもSwift3化してみることにしました。
修正箇所
privateをfileprivateに変更
before
private var rawArray: [AnyObject] = []
private var rawDictionary: [String : AnyObject] = [:]
private var rawString: String = ""
private var rawNumber: NSNumber = 0
private var rawNull: NSNull = NSNull()
after
fileprivate var rawArray: [Any] = []
fileprivate var rawDictionary: [String : Any] = [:]
fileprivate var rawString: String = ""
fileprivate var rawNumber: NSNumber = 0
fileprivate var rawNull: NSNull = NSNull()
初めてSwiftのprivateが同じファイル内からアクセス可能だと知ったときはビビりましたが、extensionとかで使うときは便利なんだよな〜ということで気持ち悪さを感じつつも使っていましたprivate。
それがSwift3からは下記のようになってすっきりしました。
- private: Javaなど他の言語と同様のスコープ
- fileprivate: Swiftの旧privateと同じファイル内で有効なスコープ
cf. SE-0025 Scoped Access Level
今回は動作を変えないよう、旧privateをfileprivateにそのまま書き換えました。
(privateに絞れるものがあればprivateに絞っても良いですね)
関数からプロパティになったので()を削除
before
if decimal == NSDecimalNumber.notANumber() { // indicates parse error
return NSDecimalNumber.zero()
after
if decimal == NSDecimalNumber.notANumber { // indicates parse error
return NSDecimalNumber.zero
もともと関数で定義されていたのがプロパティーになってたので削除(この変更の原典ってなんだろう)。
AnyObjectからAnyへ
before
let object: AnyObject = try JSONSerialization.jsonObject(with: data, options: opt)
after
let object: Any = try JSONSerialization.jsonObject(with: data, options: opt)
これはObjective-Cのid型をSwiftで扱う際に、AnyObjectではなくAnyで扱うようになった影響ですね。
AnyObjectは参照型の型全般を表すもの、Anyは値型、参照型含めた型全般を表するものですが、SwiftではStringやArrayなどが値型になっているのでそれらとの相互運用をしやすくするための変更のようです。
JSONSerialization.jsonObjectでJSONデータからobjectを作る際に返す型がAnyObjectからAnyになったので、その関連部分もすべて型をAnyに差し替えました。
cf. SE-0116 Import Objective-C id as Swift Any type
whereを,に変更
before
if let errorValue = error where errorValue.code == ErrorNotExist{
after
if let errorValue = error, errorValue.code == ErrorNotExist{
if文の中などで複数の条件節がある場合の曖昧さをなくすために書き方が変わったようです。
cf. SE-0099 Restructuring Condition Clauses
Booleanプロトコルへの適合部分を削除
before
extension JSON: Swift.Boolean {
after
extension JSON {
Booleanプロトコルが廃止されたことによる影響です。
歴史的な経緯で他のいろんな型の値をBooleanとして使ってるけど良くないのでBoolだけにしようぜということらしい。
コンパイルを通すためにBooleanプロトコルに適合させる部分だけ削除したけど本当はこのextension自体削除した方がいいのだろうか・・・?
cf. SE-0109 Remove the Boolean protocol
まとめ
ということで一応使えるようになった&Swift3の変更点の勉強になってよかった。
問題ありそうなところありましたらご指摘いただけると嬉しいです。
※Testとかまで直して確認してないので動作保証はできませんm(_ _)m
作業環境
Xcode: Version 8.0 (8A218a)
Folkした状態のまんまのswift3ブランチ
https://github.com/jollyjoester/SwiftyJSON/tree/swift3
Xcode8.0でビルドできるようにしたブランチ
https://github.com/jollyjoester/SwiftyJSON/tree/swift3-new
上記の差分
https://github.com/SwiftyJSON/SwiftyJSON/compare/swift3...jollyjoester:swift3-new?expand=1