🔰基礎技術

【Flutter実践】iPhoneアプリ開発の第一歩|プロジェクト作成からエミュレーター起動、基本設定までを徹底解説

以前の記事で、Android向けの「習慣トラッカー」アプリを作りました。
今回は、iPhone(iOS)版のセットアップと動作確認を行います。

Flutterの魔法の力で、「中身のコード(Dart)」はAndroidと全く同じものが使えます。
しかし、アプリの名前やIDなど「外枠」の設定は、Appleのルールに従って設定する必要があります。

⚠️ 注意:Macが必要です

iOSアプリの開発・ビルドには、Appleの規約によりMac(macOS)が必須です。Windowsパソコンをご利用の方は、この記事の手順は実行できません。まずはAndroid版の開発を進めましょう。

1. iOSアプリ開発の基本構造

Flutterプロジェクトの中には、Androidの時と同様に ios という専用のフォルダがあります。

イメージとしては以下の通りです。

  • lib/ フォルダ: アプリの中身。私たちがコードを書く場所。
  • ios/ フォルダ: iPhone用の額縁。アプリ名やアイコン、権限の設定などを司る場所。

2. VS CodeとXcodeの役割分担(おさらい)

環境構築編でお話しした通り、iOS開発では2つのソフトが連携して動きます。

  • VS Code: 普段のコードはここで書きます。軽くて快適です。
  • Xcode: Apple公式の開発ツールです。VS Codeで書いたコードを「iPhoneが読める言葉」に翻訳し、シミュレーターを起動する裏方の仕事をします。

基本はVS Codeだけで完結しますが、「iOS特有の初期設定」を行う時だけは、Xcodeの画面を開いた方が安全で確実です(ファイルを直接いじると壊れやすいため)。

3. iOSアプリの「戸籍」と初期設定

では、iOSアプリの必須設定である「Bundle ID(バンドルID)」と「アプリ名」を設定しましょう。
ここからは、あえてXcodeを使います。

Step 1: Xcodeで「ios」フォルダを開く

  1. VS Codeの左側のファイルツリーから ios フォルダを探します。
  2. ios フォルダを右クリックし、「Finderで開く(Reveal in Finder)」を選びます。
  3. 開いたFinderの中で Runner.xcworkspace(白いアイコン)をダブルクリックします。
    Runner.xcodeproj ではないので注意!

これでXcodeが起動します。

Step 2: Bundle ID(アプリID)の設定

Androidの「パッケージ名」にあたるもので、世界で一つだけのIDである必要があります。

  1. Xcodeの左上の 「Runner」(青いアイコン)をクリックします。
  2. 真ん中の画面で 「Signing & Capabilities」 タブを開きます。
  3. Bundle Identifier の欄を、自分のドメインの逆順+アプリ名(例: tech.simplekits.habitTracker)に変更します。

※ついでに、その下の「Team」で自分のApple IDを選択しておくと、後々実機テストをする時にスムーズです。

Step 3: アプリ名(スマホ上の表示名)の設定

デフォルトでは英語のプロジェクト名になっています。

  1. 同じくXcodeの真ん中の画面で、今度は 「Info」 タブを開きます。
  2. リストの中から 「Bundle display name」 を探します(なければ + ボタンで追加します)。
  3. ここの値を 習慣トラッカー と日本語で入力します。

設定が終わったら、Xcodeは閉じてしまって構いません。VS Codeに戻りましょう。

4. iPhoneシミュレーターの起動

VS Codeから、仮想のiPhone(シミュレーター)を呼び出します。

  1. VS Codeの右下(青い帯の部分)にあるデバイス名(例: ChromeWindows、または No Device)をクリックします。
  2. 画面上部にリストが表示されるので、「Start iOS Simulator」 を選びます。
  3. 数秒〜数十秒待つと、Macの画面上にiPhoneが現れます!

初めて起動する時は少し時間がかかります。iPhoneのホーム画面が表示されるまで気長に待ちましょう。

5. 【実装と確認】iOSで習慣トラッカーを動かす

準備は整いました。コードはAndroid編の「習慣トラッカー」と全く同じで動きます。
lib/main.dart が以下のようになっているか確認してください(前回と同じコードです)。

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Habit Tracker',
      theme: ThemeData(
        primarySwatch: Colors.indigo,
        useMaterial3: true,
      ),
      home: const HabitListScreen(),
    );
  }
}

class HabitListScreen extends StatefulWidget {
  const HabitListScreen({super.key});

  @override
  State<HabitListScreen> createState() => _HabitListScreenState();
}

class _HabitListScreenState extends State<HabitListScreen> {
  final List<String> _habits = [
    '朝に水を一杯飲む',
    '5分間ストレッチ',
    '読書をする',
  ];

  void _addHabit() {
    showDialog(
      context: context,
      builder: (context) {
        String newHabit = '';
        return AlertDialog(
          title: const Text('新しい習慣を追加'),
          content: TextField(
            autofocus: true,
            onChanged: (value) => newHabit = value,
          ),
          actions: [
            TextButton(
              onPressed: () {
                if (newHabit.isNotEmpty) {
                  setState(() {
                    _habits.add(newHabit);
                  });
                }
                Navigator.pop(context);
              },
              child: const Text('追加'),
            ),
          ],
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('今日の習慣'),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
      ),
      body: ListView.builder(
        itemCount: _habits.length,
        itemBuilder: (context, index) {
          return Card(
            margin: const EdgeInsets.all(8),
            child: ListTile(
              leading: const Icon(Icons.check_circle_outline),
              title: Text(_habits[index]),
              onTap: () {
                print('${_habits[index]} をタップしました');
              },
            ),
          );
        },
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _addHabit,
        child: const Icon(Icons.add),
      ),
    );
  }
}

デバッグ実行(F5)

VS Codeで F5 キーを押す(または「実行」→「デバッグの開始」)と、ビルドが始まります。

裏側でXcodeが一生懸命働いているため、最初の起動には数分かかります。
エラーが出ずにシミュレーター上にアプリが表示されたら成功です!追加ボタン(+)を押して、iOS特有の滑らかなアニメーションを体験してみてください。

まとめ:1つのコードで2つの世界へ

Androidで作ったアプリが、コードを1行も変えずにiPhoneでも動きました。
これがクロスプラットフォーム開発(Flutter)の最大の強みです。

iOSアプリ開発において、「設定はXcode、コードはVS Code」という使い分けを覚えておけば、よく分からないエラーに悩まされる確率をグッと下げることができます。

-🔰基礎技術