各種ライブラリのSwift3での変更点

## はじめに
Swift3に移行したところかなり仕様が変わったものがあったのでまとめておきます。

## URL(旧NSURL)
URLのStringを取り出したい時、今までは`URLString`プロパティでしたが、Swift3から`absoluteString`になりました（自動コンバートに引っかからないので公式ですが一応念のため）

## Alamofire
こちらが

```swift:swift2
Alamofire.request(.GET, URLの文字列, parameters: nil)
```

こうなります。

```swift:swift3
Alamofire.request(URLの文字列)
```

## SDWebImage
細かいところですがSDWebImageDownloaderCompletedBlockの型が自動変換では変えられませんでした。

```swift:swift2
(UIImage!, NSData!, NSError!, Bool!) -> Void
```

これが

```swift:swift3
(UIImage?, NSData?, NSError?, Bool) -> Void
```

になります。

## Realm
`allObject`の第一引数名として`ofType`、sortedの第一引数として`onProperty`が採用されています。また`ofType`に指定する型に関しては特別にselfプロパティを渡さなければいけなくなりました。例えば`class DataList: Object`に関してidでソートしたデータを取り出したい場合は

```swift
realm.objects(DataList.self).sorted(byProperty: "id")
```

というように書きます。

## RxSwift
結構変わっています。
まず基本的に今まで`rx_tap`や`rx_text`というようになっていましたが、これがすべて`rx.tap`や`rx.text`のようにrxの子プロパティ（といえば良いんでしょうか...?）に変わっています。

またRxExampleの中のImagePickerを呼び出すサンプルに関して、今までは

```swift:swift2
extension UIImagePickerController {
    static func rx_createWithParent(_ parent: UIViewController?, animated: Bool = true, configureImagePicker: (UIImagePickerController) throws -> () = { variable in }) -> Observable<UIImagePickerController> {
        return Observable.create { [weak parent] observer in
            let imagePicker = UIImagePickerController()
            let dismissDisposable = imagePicker
                .rx_didCancel
                .subscribeNext({ [weak imagePicker] in
                    guard let imagePicker = imagePicker else {
                        return
                    }
                    dismissViewController(imagePicker, animated: animated)
                    })
            do {
                try configureImagePicker(imagePicker)
            } catch let error {
                observer.on(.Error(error))
                return NopDisposable.instance
            }
            guard let parent = parent else {
                observer.on(.completed)
                return NopDisposable.instance
            }
            parent.present(imagePicker, animated: animated, completion: nil)
            observer.on(.next(imagePicker))
            return CompositeDisposable(dismissDisposable, AnonymousDisposable {
                dismissViewController(imagePicker, animated: animated)
                })
        }
    }
}
```

このようなExtensionを書き、

```swift:swift2
UIImagePickerController.rx_createWithParent(self) { picker in
    picker.sourceType = .photoLibrary
    picker.allowsEditing = true
}
```

というように呼び出していましたが、これが

```swift:swift3
extension Reactive where Base: UIImagePickerController {
    static func createWithParent(_ parent: UIViewController?, animated: Bool = true, configureImagePicker: @escaping (UIImagePickerController) throws -> () = { x in }) -> Observable<UIImagePickerController> {
        return Observable.create { [weak parent] observer in
            let imagePicker = UIImagePickerController()
            let dismissDisposable = imagePicker.rx
                .didCancel
                .subscribe(onNext: { [weak imagePicker] in
                    guard let imagePicker = imagePicker else {
                        return
                    }
                    dismissViewController(imagePicker, animated: animated)
                    })
            
            do {
                try configureImagePicker(imagePicker)
            } catch let error {
                observer.on(.error(error))
                return Disposables.create()
            }
            
            guard let parent = parent else {
                observer.on(.completed)
                return Disposables.create()
            }
            
            parent.present(imagePicker, animated: animated, completion: nil)
            observer.on(.next(imagePicker))
            
            return Disposables.create(dismissDisposable, Disposables.create {
                dismissViewController(imagePicker, animated: animated)
            })
        }
    }
}
```

と書いて、

```swift:swift3
Reactive<UIImagePickerController>.createWithParent(self) { picker in
	picker.sourceType = .camera
	picker.allowsEditing = false
}
```

このように呼び出すようになりました。これは推奨というわけではなくこう書かなければ自動変換だとここまで直してくれません...汗

## Swifter
Twitter関連を作る人には大分使われるものだと思いますが、こちらが大幅に変更されました。最近masterにswift3ブランチがマージされて、今pullしてしまうとこのバージョンになってしまうのでSwift3を使ってない人は注意してください。

こちらは変更点が大きいので少しまとめたいと思います。

### ① SuccessHandler型, FailureHandler型の導入
全てのsuccessHandlerとfailureHandlerがそれぞれ`SuccessHandler`型、`FailureHandler`型に統一されました。それぞれ`(JSON) -> Void`と`(Error) -> Void`のtypealiasなのでクロージャーの宣言を変えましょう。

### ② JSONValueが廃止されJSONに統一
`JSONValue`が無くなりすべて`JSON`となりました。`SuccessHandler`ではすべてこの`JSON`型で返ってくるため、今までDictionaryで返ってきていたところは`status.object`、配列で返ってきていたところは`status.array`とその中から取り出す形となります。

### ③ UserTag、ListTagの導入
今までメソッドによって分けられていたIDやスクリーンネームなど二つの指定の仕方があるユーザーやリストに関してこのタグを使うことでメソッドが一元化されました。

例えばIDでユーザーの情報を取りたい場合などは`.id(IDの文字列)`というものを引数として渡すことでメソッドが実行できます。

### ④ 以上の変更を経てメソッド名の大幅変更
①〜③の変更をうけてメソッド名と使い方が変わりました。短く、直感的なものになっています。
用途とメソッド名のみリストにしてもいいのですが、とりあえずどれがどう対応するのかというのも確認しようということで、旧バージョンに関しても載せたいと思います。

|用途|Swift3版|Swift2版|
|:---|---|---:|
|タイムライン取得|`getHomeTimeline(count: 個数, success: successHandler, failure: failureHandler)`|`getStatusesHomeTimelineWithCount(個数, success: successHandler, failure: failureHandler)`|
|メンション一覧取得|`getMentionsTimlineTweets(count: 個数, success: successHandler, failure: failureHandler)`|`getStatusesMentionTimelineWithCount(個数, success: successHandler, failure: failureHandler)`|
|リストタイムライン取得|`listTweets(for: ListTag, success: successHandler, failure: failureHandler)`|`getListsStatusesWithListID(ID文字列, success: successHandler, failure: failureHandler)`|
|ユーザータイムライン取得|`getTimeline(for: UserTag, count: 個数, success: successHandler, failure: failureHandler)`|`getStatusesUserTimelineWithUserID(ID文字列, count: 個数, success: successHandler, failure: failureHandler)`|
|リスト一覧|`getSubscribedLists(for: UserTag, success: successHandler, failure: failureHandler)`|`getListsSubscribedByUserWithScreenName(screenName, success: successHandler, failure: failureHandler)`|
|ツイート情報取得|`getTweet(forID: ID文字列, success: successHandler, failure: failureHandler)`|`getStatusesShowWithID(ID文字列, success: successHandler, failure: failureHandler)`|
|ユーザー情報取得|`showUser(for: UserTag, success: successHandler, failure: failureHandler)`|`getUsersShowWithScreenName(screenName, success: successHandler, failure: failureHandler)`|
|フォロー|`(for: UserTag, success: successHandler, failure: failureHandler)`|`postCreateFriendshipWithID(ID文字列, success: successHandler, failure: failureHandler)`|
|リムーブ|`unfollowUser(for: UserTag, success: successHandler, failure: failureHandler)`|`postDestroyFriendshipWithID(ID文字列, success: successHandler, failure: failureHandler)`|
|ツイート|`postTweet(status: tweetText!, inReplyToStatusID: replyID, media_ids: mediaIds, success: successHandler, failure: failureHandler)`|`postStatusUpdate(tweetText!, media_ids: mediaIds, inReplyToStatusID: replyID, success: successHandler, failure: failureHandler)`|
|ツイート削除|`destroyTweet(forID: ID文字列, success: successHandler, failure: failureHandler)`|`postStatusesDestroyWithID(ID文字列, success: successHandler, failure: failureHandler)`|
|お気に入り|`favouriteTweet(forID: ID文字列, success: successHandler, failure: failureHandler)`|`postCreateFavoriteWithID(ID文字列, success: successHandler, failure: failureHandler)`|
|お気に入り削除|`unfavouriteTweet(forID: ID文字列, success: successHandler, failure: failureHandler)`|`postDestroyFavoriteWithID(ID文字列, success: successHandler, failure: failureHandler)`|
|リツイート|`retweetTweet(forID: ID文字列, success: successHandler, failure: failureHandler)`|`postStatusRetweetWithID(ID文字列, success: successHandler, failure: failureHandler)`|
|ブロック|`blockUser(for: UserTag, success: successHandler, failure: failureHandler)`|`postBlocksCreateWithScreenName(screenName, success: successHandler, failure: failureHandler)`|
|通報|`reportSpam(for: UserTag, success: successHandler, failure: failureHandler)`|`postUsersReportSpamWithScreenName(screenName, success: successHandler, failure: failureHandler)`|

以上です。見ていただいて分かる通りSwifterだけでかなりのボリュームなのでそれで記事を作っても良かったのですが、せっかくだということで使っているいくつかのライブラリに関しても紹介させていただきました。

このようにサードパーティのライブラリひとつとってもSwift3への変更はかなり大きいものなのでしっかり対応できるように頑張っていきましょう。