最近までObjective-Cで開発してきたアプリの新たな対応でSwiftを使い始めたら、色々と考慮すべきだったなってことがあったので、それについての話。
#考慮すべきだった点その1 カテゴリ
Objective-CやSwiftでは、既存のクラスを拡張する機能を持っています。
Objective-CではCategory、Swiftではextensionと呼ばれる機能です。
Objective-Cで作成したカテゴリはSwiftからでも呼び出せるのですが、例えば、以下のようなカテゴリだった場合、少し困ったことになります。
- (NSDate *)diffrenceDays:(NSInteger)days
{
NSCalendar *calendar = [[NSCalendar alloc]initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *dateComponents = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitWeekday
fromDate:self];
dateComponents.day += days;
return [calendar dateFromComponents:dateComponents];
}
これは、インスタンス化されたNSDateからdays日前、もしくはdays日後のNSDateを返り値とするNSDateの拡張メソッドです。
これをSwiftから呼び出してみると以下のようになります。
// 現在日時のNSDateを生成
let nsdate = NSDate()
// 三日後の日付を取得する(Date型)
let date = nsdate.diffrenceDays(3)
Swiftではバージョン3からNSDate型ではなく、Date型が採用されているため、Objective-CのNSDate型のカテゴリをDate型から呼び出すことができないので、それを使用する場合はNSDate型を使用する必要があります。
ですがSwiftとObjective-Cの連携の性質上、SwiftでObjective-C側のメソッドを呼び出す場合に、NSDateの引数や返り値はDate型になってしまいます。
そういった場合、何が都合が悪いかというと、先ほどの例で言うと、返り値がNSDateではなく、Date型のため、そこからさらにNSDateのカテゴリのメソッドを使用したい場合に、一度asでNSDate型に戻してやる必要があると言う点です。
// 現在日時のNSDateを生成
let nsdate = NSDate()
// 三日後の日付を取得する(Date型)
let date = nsdate.diffrenceDays(3)
// さらに三日後の日付を取得する
let nsdate2 = date as! NSDate
let date2 = nsdate2.diffrenceDays(3)
この例は極端な例ですが、NSDateは、様々なアプリで使用が想定されますし、その分カテゴリで拡張するのはかなり一般的で、過去の資産がたくさんある中で、新たにSwiftで使用し始めるのに毎回asで対応するのは辛い部分があります。
NSDate以外にもNSDataやNSCalendarなどのいくつかの型名はObjective-CとSwiftで名前が変わっているので、Objective-Cのカテゴリを使用する際には、Swift側でObjective-Cの型名を指定してやらなければいけません。
##対応策
1.諦める。大人しく必要な時はasでNSDateとDateを切り替える。
2.SwiftのDateのextensionにNSDateと同じ内容の物を作る
##結論
どちらにせよめんどくさい。
#考慮すべきだった点その2 ネットワーク
ネットワーク処理とSwiftは最近ではCodableといったJsonをいい感じに型に沿ったStructに変換してくれる機能が出てきて話題になりましたが、Objective-Cでは、JsonをNSDictionaryに変換するのが一般的ではないかと思います。
単純に完全に新規のネットワークを作成するのであればSwiftでCodableを使用してなんて考えたいところですが、開発期間などを考えると、Objective-Cで作成された既存の通信処理をSwift側で使用することもあります。
その場合、Dictionaryの中身の型が保証されていない場合、取り出す際にasを使用して、Any型からキャストしなければならなかったりするので、結局Objective-Cとやっていることが同じでSwiftの旨味を感じれない開発になったりします。
##対応策
1.諦める。asでキャストする。
2.意地でもSwift用のネットワークの処理を書く
##結論
どちらにせよめんどくさい。
#まとめ
まあこんなこと言ってるけど、SwiftだったらOptionalとかモダンな文法とかあって楽しいし、バグも減るんじゃないかって思うから使うべきだと思う。
でも、過去の遺産をどうするかも同時に考えたいって思った。