こんにちは。開発部でiOSエンジニアをしている野口です。
Flutterエンジニアをやっていましたが今年からiOSエンジニアに転向したので思っていることを書こうという記事になります。
なぜiOSに転向したのか
Flutterをやっていると、外部のパッケージを入れる際にネイティブコード書かないといけないなどネイティブの知識を要求されるパターンがあり以前からネイティブに興味がありました。
そんな中で社内でiOSエンジニアのポジションが必要とされていたため、良いチャンスだと思い転向しました。
また、数年前まではクロスプラットフォームでFlutterがイケイケだと思っていましたが(日本においては)、 最近は複数のクロスプラットフォームを検討した結果、React NativeやKMPなどが採用されるケースも多々見るようになったのでどのクロスプラットフォームも良くなってきている印象です。
その状況においてもモバイルアプリは結局ネイティブの知識を必要とするため、ネイティブができることは今後のキャリア的にもプラスになるかと思っています。
iOSに転向してどうか
キャッチアップについて
まず、思ったのは体系的な情報が全然ないなと。
本はそれなりに出ますが、ほとんどSwiftUIでUIKitに関する本は全く出ていないなと思いました。
デリッシュキッチンでは主にUIKit、Storyboardが使用されているため、ここら辺の情報が欲しいのですが、公式のチュートリアルくらしかありませんでした。
結局、UIKitはやりながら覚えています。最近はAIに聞いたら良い感じに答えてくれるのでありがたいです。
Storyboardは検索してもXcodeのバージョンが古いものが多く、中々参考になるものが出てきません。また、GUIで操作するものなのでAIに聞くこともできないので絶賛苦労しています。
ここら辺はチームの方針として、StoryboardはUIKitのコードもしくはSwiftUIに書き換えていこうと話し合ってるので今後Storyboardは廃止する方針です。
逆にSwiftUIはFlutterのwidgetシステムに似ているので、Flutterの知識があると理解が早いです。というかほとんど同じです。
実際に以下のコードを比較してみます。
中央にボタンを表示するコードですが、見た目はほとんど同じです。
body
が画面全体を表現していおり、その中にボタンを配置しているのでFlutterもSwiftUIも同じ考え方をしています。
Flutter
import 'package:flutter/material.dart'; class CenterButtonScreen extends StatelessWidget { const CenterButtonScreen({super.key}); @override Widget build(BuildContext context) { return Scaffold( body: Center( child: ElevatedButton( onPressed: () {}, child: const Text('ボタン'), ), ), ); } }
SwiftUI
import SwiftUI struct CenterButtonScreen: View { var body: some View { Button("ボタン") {} .buttonStyle(.borderedProminent) .frame(maxWidth: .infinity, maxHeight: .infinity) } }
UIKitでは、中央にボタンを表示するためには、以下のようにコードを書く必要があり、見た目がだいぶ変わります。
UIKit
import UIKit class CenterButtonViewController: UIViewController { private func createButton() -> UIButton { let button = UIButton(type: .system) button.setTitle("ボタン", for: .normal) button.backgroundColor = .systemBlue button.setTitleColor(.white, for: .normal) button.layer.cornerRadius = 8 return button } override func viewDidLoad() { super.viewDidLoad() let button = createButton() button.translatesAutoresizingMaskIntoConstraints = false view.addSubview(button) NSLayoutConstraint.activate([ button.centerXAnchor.constraint(equalTo: view.centerXAnchor), button.centerYAnchor.constraint(equalTo: view.centerYAnchor), button.widthAnchor.constraint(equalToConstant: 100), button.heightAnchor.constraint(equalToConstant: 44) ]) button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside) } @objc private func buttonTapped() { // ボタンを押した時の処理 } }
viewの配置には以下のように作成したボタンに対して制約をつけてあげる必要があるため、コードが冗長になるなーと感じています。 ですが、最近慣れてきてるのでそんなに気にならなくなってきました。
NSLayoutConstraint.activate([ button.centerXAnchor.constraint(equalTo: view.centerXAnchor), button.centerYAnchor.constraint(equalTo: view.centerYAnchor), button.widthAnchor.constraint(equalToConstant: 100), button.heightAnchor.constraint(equalToConstant: 44) ])
開発環境の違い
Swiftの言語仕様、公式のフレームワークが充実している
CombineなどApple純正のフレームワークを提供してくれるのは良いです。
Combineでは非同期処理や状態管理を行なってくれますが、Flutterでやろうとすると、Riverpodなどの外部パッケージを使用する必要があります。
外部パッケージではサポートされなくなることもあり、長期的なメンテナンスを考えるとあまり依存したくはなくはないものにはなるので、それを公式が提供するのは安心感があります。
また、Flutterでは不変なクラスを作るためにfreezed
などの外部パッケージとbuild_runner
による自動生成が必要ですが、Swiftではstruct
を使うだけで実現できるのが魅力的です。
エディターの違い
Flutter開発ではVSCodeを使用していましたが、iOS開発ではXcodeを使用します。Xcodeは癖が強いため最初は辛かったです。
特に私はgitの操作をvscodeのGit Graphで主に行なっていたので、 Xcodeではgitクライアントをどうしようかと、TerminalかSourceTreeを使用するかなど考えて右往左往しています。
また、XcodeではAIのサポートがあまり充実していないので、昨今のAIブームに乗り切れないのが悲しいなと思います。
github copitlotを入れることはできますが、chat形式で質問はできない。。。と思ってたんですが、 記事を書いている時に調べたら最近chatができるようになったみたいです。
最近はCursorでiOS開発できないかなと思って試行錯誤しておりますが、Cursorからビルドすると遅すぎて辛いのでCursorはコードを書いてもらうのとgitクライアントとして使用しています。
CursorでiOS開発しようとした時に参考にしたのはこちらの記事です。
最後に
2ヶ月しか経ってないので、浅ーいことしか書けていないのですが、同じモバイル開発でも結構環境が変わって、キャッチアップが大変でした。
FlutterからiOSに転向を考えている方の参考になれば嬉しいです。
もっと深い内容を書きたいですが、もう少しだけiOS開発をしてから機会があれば記事を書きたいと思います。
ご覧いただきありがとうございました。