LoginSignup
1
3

More than 5 years have passed since last update.

Objective-CのプロジェクトにSwiftを入れる前に考えたいこと

Last updated at Posted at 2017-12-07

最近までObjective-Cで開発してきたアプリの新たな対応でSwiftを使い始めたら、色々と考慮すべきだったなってことがあったので、それについての話。

考慮すべきだった点その1 カテゴリ

Objective-CやSwiftでは、既存のクラスを拡張する機能を持っています。
Objective-CではCategory、Swiftではextensionと呼ばれる機能です。

Objective-Cで作成したカテゴリはSwiftからでも呼び出せるのですが、例えば、以下のようなカテゴリだった場合、少し困ったことになります。

NSDate+differenceDays.m
- (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とかモダンな文法とかあって楽しいし、バグも減るんじゃないかって思うから使うべきだと思う。
でも、過去の遺産をどうするかも同時に考えたいって思った。

1
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
3