初めまして。
サイバーエージェントの子会社の株式会社マッチングエージェントでエンジニアをしている海川です。
2017年3月1日に開催されたCA.swift #2で発表した内容から少し変えたものを語っていきます。
当日の資料はこちら
スライドでは合宿の話が多いですが、こちらの記事では省いてSwift化の部分だけにしてあります。
目次
Swift化した理由
swift化した理由は2つあります
1つ目は、エンジニアとしての今後の成長のためです。
当たり前の話ですが、今後iOSエンジニアとしてやっていくなら、Objective-CをやるよりSwiftを学んだ方がいいです。
Objective-CからSwiftに変換するのに時間がかかってしまいますが、それ以上の価値があると判断しました。
2つ目は、エンジニア採用のためです。
以前、iOSエンジニアを採用しようとした際に、弊社のアプリがObjective-Cでできていると伝えたら、「Objective-Cは読みたくない」と言われてしまったことがありました。
その人は他の部署へ行ってしまいました。優秀なエンジニアだっただけに非常に残念でした。
今後このようなことがないようにしたい、という思いがあります。
Swift化ツールについて
結論から言ってしまうと、objc2swift一択です
Swift化ツールについては、調べた結果代表的なものは3つくらいありました
iSwift、Swiftify、objc2swiftです。 このサイトを参考にしました。
iSwiftはほとんど試していませんが、Swiftifyとobjc2swiftを試してみました。
- Swiftifyは有料で、Swift2.3とSwift3.0に変換できる
- objc2swiftは無料で、Swift2.3に変換できる
という差があり、Swiftifyの方が便利そうなのですが、
- Swift2.3になったコードはXcodeからの警告にしたがって修正すれば、Swift3.0環境に問題なく変換できる
- 変換自体がほとんどうまくいかないので、結局自分で修正する必要がある
という点です
以下のコードをobjc2swiftで変換すると、
@implementation CCTopic
- (id)initWithDictionary:(NSDictionary *)dictionary
{
if (self = [super initWithDictionary:dictionary]) {
_topicId = [dictionary[@"_id"] intValue];
_title = @"特集";
_color = [CCColorHelper colorWithHex:dictionary[@"color"]];
CCUser *me = [CCAppGlobalModel sharedModel].user;
NSDictionary *numDic = dictionary[@"member"];
if ([numDic isKindOfClass:[NSDictionary class]]) {
NSNumber *num = me.isMale ? numDic[@"count"][@"female"] : numDic[@"count"][@"male"];
_count = num.intValue;
}
NSDictionary *titleDic = dictionary[@"title"];
if ([titleDic isKindOfClass:[NSDictionary class]]) {
_specialTitle = me.isMale ? titleDic[@"female"] : titleDic[@"male"];
}
NSDictionary *searchDic = dictionary[@"readOnlyCondition"];
if ([searchDic isKindOfClass:[NSDictionary class]]) {
_uneditableConditions = [[CCSearchConditions alloc] initWithDictionary:searchDic[@"user"]];
}
}
return self;
}
@end
以下のようになります
class CCTopic: CCEntity {
var topicId: Int32
var count: Int32
var title: String
var specialTitle: String
var color: UIColor
var uneditableConditions: CCSearchConditions
init(dictionary: [AnyObject: AnyObject]) {
if self = super(dictionary: dictionary) {
_topicId = dictionary["_id"].intValue()
_title = "特集"
_color = CCColorHelper.colorWithHex(dictionary["color"])
var me = CCAppGlobalModel.sharedModel().user
var numDic = dictionary["member"]
if numDic.isKindOfClass(NSDictionary.class()) {
var num = me.isMale ? numDic["count"]["female"] : numDic["count"]["male"]
_count = num.intValue
}
var titleDic = dictionary["title"]
if titleDic.isKindOfClass(NSDictionary.class()) {
_specialTitle = me.isMale ? titleDic["female"] : titleDic["male"]
}
var searchDic = dictionary["readOnlyCondition"]
if searchDic.isKindOfClass(NSDictionary.class()) {
_uneditableConditions = CCSearchConditions(dictionary: searchDic["user"])
}
}
return self
}
}
スライドの写真にもある通り、エラーが大量に出ています。これはSwitifyを使ってもエラーが大量に出ます。有料ソフトだからといって、変換が楽になるということはないようです。
なので、有料のソフトを使う必要性はあまりないように思われます。objc2swift一択ですね
Swift化するときのポイント
実際やった経験を踏まえて、Swift化する上でのポイントを3つほどあげます
1つ目は、Swift化する際の順番は、呼び出される側からやった方がいい、ということです。
Objective-CをSwiftから呼び出す場合、以下のようになってしまいます
このように ! ばかりになってしまいますね。
もしnilの変数が紛れていた場合、気づかぬうちにエラーになってしまいます。これは非常に危険なので、呼ばれる側からやりましょう。
2つ目は、ある程度エラーを気にせずに一気にやってしまうことも重要だ、ということです。
Objective-CとSwiftの接続部分は面倒なポイントが多いので、そういう接続部分は極力減らした方が懸命です。
例えばmodel部分は一気にやってしまうとか、ViewControllerとそれ以外で分けてやるとか、ViewControllerとViewModelは一緒にSwift化するとか、がっつりやった方が早いこともあると思います。
3つ目は、早めにコード規約を決めよう、ということです。
Objective-Cに比べて、SwiftはOptionalができたので、変数一つ取っても3通りの記載方法があります。
新しいものを作るときにstructを使うのか、classを使うのか、enumを使うのか、など選択しないと行けません。
いろいろできて楽しい反面、複数人で開発しているとぐちゃぐちゃになりやすいので、しっかり決めましょう。
最後に
SwiftはObjective-Cより厳格で楽しいです。
ちゃんとしたコード書いてるなーという実感が湧きます。
Swift化は自分のためにも、プロダクトのためにもなるので、迷っているとしたら、絶対にやるべきです。
このSwift化の最初のきっかけは開発合宿でした。開発合宿の記事もあるのでぜひ見てみてください。
あと、CASwift.#2の別のスライドの記事もぜひどうぞ。