見出し画像

ChatGPT-4oでiPad用の電卓アプリ作ってみたよ前編

ChatGPT-4oの登場でにわかに盛り上がってて、そういえば最近ChatGPT Plus、あんまり使ってないし、なんか試しに使ってみたいなと。

そう、iPad mini 6を手に入れてからずっと不便に思ってることがあって。なんで標準電卓無くしたの?ねぇ、なんで??

ってことで、「そうだ電卓を作ろう」と思い立ったわけです。

けっこう途中、紆余曲折あったり、挫折しそうになったりしたので、ちょちょっとまとめた形ではありますが、ChatGPTくんと一緒に電卓を作った道筋を振り返りたいと思います。

制作環境:
Windows11 Home。
ChatGPTはChatGPT Plus。
ブラウザはGoogle ChromeとMicrosoft Edge。
テキストエディターはBrackets。


まずはお伺いを立てる

ボク:
iPad用のアプリを作るには、どの言語が一番いいですか?

ChatGPT:
iPad用のアプリを作るには、主に以下の言語が使われますが、目的や開発環境によって最適な言語が異なります。

  1. Swift:

    • 概要: Appleが開発したプログラミング言語で、iOS、iPadOS、macOS、watchOS、tvOS用のアプリ開発に最適です。

    • 利点: 高速で安全、モダンな言語。Appleの最新のAPIやフレームワーク(SwiftUIなど)に完全に対応しています。

    • 開発ツール: Xcode(Appleが提供する統合開発環境)

  2. Objective-C:

    • 概要: Swiftが登場する前に主に使われていた言語。現在でも多くのレガシーコードやライブラリがObjective-Cで書かれています。

    • 利点: Swiftとの互換性があるので、既存のObjective-Cコードを持つプロジェクトでも問題なく使用可能。

    • 開発ツール: Xcode

  3. Dart(Flutterフレームワークと併用):

    • 概要: Googleが開発したプログラミング言語で、Flutterフレームワークを使用してクロスプラットフォームのアプリを開発できます。

    • 利点: 単一のコードベースでiOSとAndroidの両方に対応したアプリを開発できる。

    • 開発ツール: Visual Studio Code、Android Studio

  4. JavaScript(React NativeやIonicフレームワークと併用):

    • 概要: Web技術を使用してネイティブアプリを開発するためのアプローチ。React NativeやIonicを使用することで、クロスプラットフォームのアプリを作成できます。

    • 利点: 一つのコードベースでiOSとAndroidに対応可能。Web開発の知識を活用できる。

    • 開発ツール: Visual Studio Code、WebStorm

結論: iPad用のアプリを作成する際には、主にSwiftが最適な選択肢です。Swiftは最新の言語であり、Appleのエコシステム全体に対応しているため、特にiPadOS向けのアプリ開発において優れたパフォーマンスと最新の機能を提供します。


ボク:
無料でiPad用の電卓アプリを作りたいんだけど、その場合はどれがいいですか?

ChatGPT:
無料でiPad用の電卓アプリを作りたい場合、以下の言語とツールの組み合わせが最適です:

Swift + Xcode

  • 概要: SwiftはAppleが推奨するプログラミング言語で、Xcodeは公式の統合開発環境(IDE)です。

  • 利点:

    • Apple製のツールであるため、iPadアプリ開発に最適です。

    • 無料で利用できます(Macが必要)。

    • 豊富なドキュメントとコミュニティサポートがあります。

手順:

  1. Xcodeのインストール:

    • Appleの公式サイトまたはMac App StoreからXcodeをダウンロードしてインストールします。

  2. 新しいプロジェクトの作成:

……(中略)……

ChatGPT:
無料で高品質な電卓アプリを作成するために、SwiftとXcodeを使うことを強くお勧めします。


ボク:
Windowsで作る場合はどれがいいですか?

ChatGPT:
WindowsでiPad用の電卓アプリを作る場合、以下のツールとフレームワークの組み合わせが最適です:

Flutter + Dart

  • 概要: FlutterはGoogleが開発したクロスプラットフォームのUIフレームワークで、Dart言語を使用します。Windows上で開発でき、iOS向けのアプリも作成可能です。

  • 利点:

    • 一つのコードベースでiOSとAndroidの両方に対応。

    • 無料で利用可能。

    • 高いパフォーマンスと豊富なウィジェット。

    • Windows上での開発環境が整っている。

手順:

  1. Flutterのインストール:

……(中略)……

ChatGPT:
この方法により、Windows上でiPad用の電卓アプリを効率的に開発することができます。

ウェブアプリを提案してみる

うーん、なんか面倒なことになってきたぞ?もうウェブアプリでいいのになと思ったので、

ボク:
ウェブアプリとして実装する場合はどういう方法で作れますか?

ChatGPT:
ウェブアプリとしてiPadで動作する電卓アプリを作成する場合、以下の方法があります。ウェブアプリとして作成することで、iOSだけでなく、他のプラットフォームでも利用可能です。

使用する技術:

  1. HTML: アプリの構造を作成する。

  2. CSS: アプリのスタイリングを行う。

  3. JavaScript: アプリの動作を制御する。

フレームワークとライブラリ(オプション):

  • React: モダンなUIフレームワーク。コンポーネントベースで開発しやすい。

  • Vue.js: 軽量で学習しやすいUIフレームワーク。

  • Angular: 大規模アプリケーションに適したフルスタックフレームワーク。

手順:

1. プロジェクトのセットアップ:

  • プロジェクトフォルダを作成し、基本的なHTMLファイルを作成します。

2. HTMLファイルの作成:

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>電卓アプリ</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div id="calculator">
        <div id="display">0</div>
        <div id="buttons">
            <!-- 電卓のボタンを配置 -->
            <button>1</button>
            <button>2</button>
            <button>3</button>
            <button>+</button>
            <button>4</button>
            <button>5</button>
            <button>6</button>
            <button>-</button>
            <button>7</button>
            <button>8</button>
            <button>9</button>
            <button>*</button>
            <button>0</button>
            <button>.</button>
            <button>=</button>
            <button>/</button>
            <button>AC</button>
        </div>
    </div>
    <script src="script.js"></script>
</body>
</html>

3. CSSファイルの作成:

/* styles.css */
body {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    background-color: #f0f0f0;
    font-family: Arial, sans-serif;
}

#calculator {
    display: grid;
    grid-template-rows: 1fr 4fr;
    width: 300px;
    background-color: #fff;
    border-radius: 10px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

#display {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    padding: 20px;
    font-size: 2em;
    background-color: #222;
    color: #fff;
    border-top-left-radius: 10px;
    border-top-right-radius: 10px;
}

#buttons {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 10px;
    padding: 10px;
}

button {
    font-size: 1.5em;
    padding: 20px;
    background-color: #e0e0e0;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    transition: background-color 0.3s;
}

button:hover {
    background-color: #d0d0d0;
}

button:active {
    background-color: #c0c0c0;
}

4. JavaScriptファイルの作成:

// script.js
const display = document.getElementById('display');
const buttons = Array.from(document.querySelectorAll('button'));
let currentInput = '';
let previousInput = '';
let operator = '';

buttons.forEach(button => {
    button.addEventListener('click', () => {
        const value = button.innerText;

        if (value === 'AC') {
            currentInput = '';
            previousInput = '';
            operator = '';
            display.innerText = '0';
        } else if (['+', '-', '*', '/'].includes(value)) {
            operator = value;
            previousInput = currentInput;
            currentInput = '';
        } else if (value === '=') {
            currentInput = eval(`${previousInput} ${operator} ${currentInput}`);
            display.innerText = currentInput;
            operator = '';
            previousInput = '';
        } else {
            currentInput += value;
            display.innerText = currentInput;
        }
    });
});

デプロイ方法:

  1. ローカルでのテスト:

    • HTMLファイルをブラウザで開いて動作確認を行います。

  2. ウェブサーバーにデプロイ:

    • GitHub Pages、Netlify、Vercelなどの無料のホスティングサービスを使って、ウェブアプリを公開します。

  3. PWA(プログレッシブウェブアプリ)として実装:

    • PWAとして実装することで、オフラインでも動作し、ホーム画面にアイコンを追加できるようになります。これには、manifest.jsonファイルとService Workerを追加する必要があります。

PWAの基本設定:

1. manifest.json:

{
  "name": "電卓アプリ",
  "short_name": "電卓",
  "start_url": ".",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#000000",
  "icons": [
    {
      "src": "icon.png",
      "sizes": "192x192",
      "type": "image/png"
    }
  ]
}

2. Service Worker:

// service-worker.js
self.addEventListener('install', event => {
    event.waitUntil(
        caches.open('calculator-cache').then(cache => {
            return cache.addAll([
                '/',
                '/index.html',
                '/styles.css',
                '/script.js',
                '/icon.png'
            ]);
        })
    );
});

self.addEventListener('fetch', event => {
    event.respondWith(
        caches.match(event.request).then(response => {
            return response || fetch(event.request);
        })
    );
});

3. Service Workerの登録:

if ('serviceWorker' in navigator) {
    window.addEventListener('load', () => {
        navigator.serviceWorker.register('/service-worker.js')
            .then(registration => {
                console.log('ServiceWorker registration successful with scope: ', registration.scope);
            }, err => {
                console.log('ServiceWorker registration failed: ', err);
            });
    });
}

これらの手順に従うことで、iPadでも利用可能なウェブベースの電卓アプリを作成することができます。

ボク:
PWAの基本設定の「3. Service Workerの登録」はどのファイルに登録するのですか?

ChatGPT:
「3. Service Workerの登録」は、通常、メインのHTMLファイル(例:index.html)のスクリプトセクションに追加します。具体的には、index.htmlの<head>または<body>タグ内に次のスクリプトタグを追加します。

index.htmlの例:

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>電卓アプリ</title>
    <link rel="stylesheet" href="styles.css">
</head>
<body>
    <div id="calculator">
        <div id="display">0</div>
        <div id="buttons">
            <!-- 電卓のボタンを配置 -->
            <button>1</button>
            <button>2</button>
            <button>3</button>
            <button>+</button>
            <button>4</button>
            <button>5</button>
            <button>6</button>
            <button>-</button>
            <button>7</button>
            <button>8</button>
            <button>9</button>
            <button>*</button>
            <button>0</button>
            <button>.</button>
            <button>=</button>
            <button>/</button>
            <button>AC</button>
        </div>
    </div>
    <script src="script.js"></script>
    <script>
        if ('serviceWorker' in navigator) {
            window.addEventListener('load', () => {
                navigator.serviceWorker.register('/service-worker.js')
                    .then(registration => {
                        console.log('ServiceWorker registration successful with scope: ', registration.scope);
                    }, err => {
                        console.log('ServiceWorker registration failed: ', err);
                    });
            });
        }
    </script>
</body>
</html>

ファイル構成の例:

/project-root
  ├── index.html
  ├── styles.css
  ├── script.js
  ├── manifest.json
  └── service-worker.js

ファイルの詳細:

  1. index.html:

    • メインのHTMLファイル。

    • Service Workerの登録スクリプトを含む。

  2. styles.css:

    • CSSファイル。スタイルの定義を含む。

  3. script.js:

    • JavaScriptファイル。電卓の機能を実装。

  4. manifest.json:

    • PWAのマニフェストファイル。アプリのメタデータを定義。

  5. service-worker.js:

    • Service Workerファイル。オフラインキャッシュ機能などを実装。

ChatGPT:
この設定により、あなたのウェブアプリはPWAとして機能し、オフラインでも動作するようになります。また、ホーム画面に追加することも可能です。

ボク:
ファイルをサーバーにアップロードしました。 iPadでオフラインで使うにはどうしたらいいですか?

ChatGPT:
iPadでオフラインで使えるようにするためには、以下の手順を行います:

  1. ウェブサイトを訪れる:

    • iPadのSafariブラウザで、アップロードしたウェブアプリのURLにアクセスします。

  2. PWAとしてインストール:

    • アクセスしたウェブページのURLバーの右側にある共有アイコン(四角に上向きの矢印)をタップします。

    • 「ホーム画面に追加」を選択します。

    • 表示された画面で「追加」をタップします。これで、ウェブアプリがホーム画面にアイコンとして追加されます。

  3. オフラインキャッシュの確認:

    • ホーム画面に追加されたアイコンをタップして、アプリを開きます。

    • アプリがオフラインキャッシュ機能を持っている場合、この時点でService Workerがインストールされ、必要なリソースがキャッシュされます。

  4. オフラインでの利用:

    • アプリを一度オンラインで開いた後、オフラインモードに切り替えてもアプリが動作することを確認します。

    • インターネット接続を切って、アプリを再度開いてみてください。キャッシュされたコンテンツが正しく表示されるはずです。

具体的な手順の例:

  1. ウェブサイトを訪れる:

    • iPadでSafariを開き、アップロードしたウェブアプリのURL(例:http://yourdomain.com)にアクセスします。

  2. ホーム画面に追加:

    • URLバーの右側にある共有アイコンをタップします。

    • 「ホーム画面に追加」を選択します。

    • 名前を入力し、「追加」をタップします。

  3. オフラインキャッシュの確認:

    • ホーム画面に追加されたアイコンをタップして、アプリを開きます。

    • アプリがオンラインで正常に動作することを確認します。

  4. オフラインでの利用:

    • iPadを機内モードに切り替えるか、Wi-Fiをオフにします。

    • ホーム画面のアイコンをタップしてアプリを開き、オフラインでも動作することを確認します。

トラブルシューティング:

  • Service Workerが正しく登録されない場合:

    • Safariのデベロッパーツールを使用して、Service Workerの状態を確認します。

    • JavaScriptコンソールでエラーメッセージがないか確認します。

  • リソースがキャッシュされない場合:

    • service-worker.jsファイルでキャッシュするリソースが正しく指定されているか確認します。

    • キャッシュストレージの名前が一意であることを確認します。

例:

// service-worker.js
self.addEventListener('install', event => {
    event.waitUntil(
        caches.open('calculator-cache').then(cache => {
            return cache.addAll([
                '/',
                '/index.html',
                '/styles.css',
                '/script.js',
                '/manifest.json',
                '/icon.png'
            ]);
        })
    );
});

self.addEventListener('fetch', event => {
    event.respondWith(
        caches.match(event.request).then(response => {
            return response || fetch(event.request);
        })
    );
});

ChatGPT:
この設定により、iPadでオフラインでも使用できる電卓アプリを実装できます。

とりあえず動く電卓できた!

ボク:
safariでオフラインで開くことができました!

ChatGPT:
オフラインでもアプリが正常に動作することが確認できてよかったです!以下に、さらに使いやすくするための追加のヒントをいくつか提供します。

追加のヒント

1. アプリアイコンとスプラッシュスクリーン:

  • アプリのアイコンとスプラッシュスクリーンを設定することで、見栄えを良くし、ユーザー体験を向上させることができます。

// manifest.json
{
  "name": "電卓アプリ",
  "short_name": "電卓",
  "start_url": ".",
  "display": "standalone",
  "background_color": "#ffffff",
  "theme_color": "#000000",
  "icons": [
    {
      "src": "icon-192x192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "icon-512x512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
}

2. オフラインデータの更新:

  • アプリが更新されたときにキャッシュを更新するためのロジックを追加します。これにより、ユーザーが常に最新のバージョンを利用できるようになります。

// service-worker.js
self.addEventListener('install', event => {
    event.waitUntil(
        caches.open('calculator-cache-v1').then(cache => {
            return cache.addAll([
                '/',
                '/index.html',
                '/styles.css',
                '/script.js',
                '/manifest.json',
                '/icon-192x192.png',
                '/icon-512x512.png'
            ]);
        })
    );
});

self.addEventListener('activate', event => {
    const cacheWhitelist = ['calculator-cache-v1'];
    event.waitUntil(
        caches.keys().then(cacheNames => {
            return Promise.all(
                cacheNames.map(cacheName => {
                    if (!cacheWhitelist.includes(cacheName)) {
                        return caches.delete(cacheName);
                    }
                })
            );
        })
    );
});

self.addEventListener('fetch', event => {
    event.respondWith(
        caches.match(event.request).then(response => {
            return response || fetch(event.request);
        })
    );
});

3. ユーザーインターフェースの改善:

  • 電卓のデザインを改善し、使いやすさを向上させるためのCSSを調整します。

  • レスポンシブデザインを取り入れ、異なる画面サイズでも使いやすいようにします。

/* styles.css */
body {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    background-color: #f0f0f0;
    font-family: Arial, sans-serif;
}

#calculator {
    display: grid;
    grid-template-rows: 1fr 4fr;
    width: 90%;
    max-width: 400px;
    background-color: #fff;
    border-radius: 10px;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

#display {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    padding: 20px;
    font-size: 2em;
    background-color: #222;
    color: #fff;
    border-top-left-radius: 10px;
    border-top-right-radius: 10px;
}

#buttons {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 10px;
    padding: 10px;
}

button {
    font-size: 1.5em;
    padding: 20px;
    background-color: #e0e0e0;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    transition: background-color 0.3s;
}

button:hover {
    background-color: #d0d0d0;
}

button:active {
    background-color: #c0c0c0;
}

@media (min-width: 600px) {
    button {
        padding: 30px;
    }
}

4. エラーハンドリングの追加:

  • 予期しないエラーやネットワークエラーに対処するためのエラーハンドリングを追加します。

// script.js
buttons.forEach(button => {
    button.addEventListener('click', () => {
        try {
            const value = button.innerText;

            if (value === 'AC') {
                currentInput = '';
                previousInput = '';
                operator = '';
                display.innerText = '0';
            } else if (['+', '-', '*', '/'].includes(value)) {
                operator = value;
                previousInput = currentInput;
                currentInput = '';
            } else if (value === '=') {
                currentInput = eval(`${previousInput} ${operator} ${currentInput}`);
                display.innerText = currentInput;
                operator = '';
                previousInput = '';
            } else {
                currentInput += value;
                display.innerText = currentInput;
            }
        } catch (error) {
            display.innerText = 'Error';
            currentInput = '';
            previousInput = '';
            operator = '';
        }
    });
});

ChatGPT:
これらの改善により、さらに使いやすく、魅力的なオフライン対応の電卓アプリを提供することができます。質問やさらなるサポートが必要な場合は、お知らせください。

この後の流れ

この調子で載せてくと10倍くらいになりそうなので、この後の流れをかいつまんで説明。

UIの変更

UIの変更をします。
ボタンの1列目は「AC」「C」「%」「+」、
2列目は「1」「2」「3」「-」、
3列目は「4」「5」「6」「*」、
4列目は「7」「8」「9」「/」、
5列目は「0」「00」「.」「=」とします。
ACはオールクリア。現在入力されているデータをすべて削除。
Aは入力中の値を0に。
%は入力中の値を100で割った数に。
00は0を2つ追加。
「.」は「.」入力後は小数点の入力に。

チェーン計算への対応

「100」「+」「200」「/」「4」「=」の順番で入力すると「200」「/」「4」「=」だけ計算されて、答えが50になります。
修正案としては、「100」「+」「200」の後に「+, -, *, /」が入力された場合は、その時点で「100+200」の結果を出す必要があります。

入力中の式表示機能を追加

もうひとつ機能を追加します。
表示欄に、現在入力されている値と演算子が表示されるようにします。 2行にして、例えば
上の行:100+
下の行:200
という感じに。上の行はフォントを少し小さくしてください。

もろもろバグの修正

「100+」と入力した後に「200」と入力すると、上の行が「100+」、下の行が「200」となります。その次に「=」と入力すると、上の行が「100+300」、下の行が「300」となります。 修正案としては、「=」が入力された場合は、上の行をクリアし、下の行に結果を表示とします。

一つ修正点を見つけました。
下の行が「0」の時に「00」ボタンを押すと「00」となります。
下の行が「0」の時は「00」ボタンを押してもスルーするようにしてください。

ChatGPTの修正を反映しても動作が直っていなかったので、業を煮やしてscript.jsの中のJavascriptを読んで問題箇所に目星をつけることに。↓

「currentInput」の初期値が「0」ではなく空文字’’になっているので、「00」ボタンが押された際の「else if (value === ’00') {」の中の「if (currentInput !== '0') {」が機能していません。「currentInput」の初期化の際に「0」を入力するか、判定部分を「if (currentInput !== '0' || currentInput !== ''){」とする必要があります。

「.」ボタンの動作も修正が必要です。 下の行が「0」の時に「.」が押されたら「0.」となる。下の行が「0」以外の整数の場合は現状通り。下の行が「0.」もしくは小数の場合は無反応とします。

計算結果のコピー機能の追加

もうひとつ機能を追加したいのですが、「表示欄をタップしたら、OSのクリップボードに結果(下の行の値)の数値をコピーする」機能を追加できますか?
可能であればどこかに「コピーしました」と表示されるとなお良いです。

上の行に値がある時と無い時で行の高さが変わると、ボタンが押しづらいので、上の行、下の行の高さを固定にしたいです。

「コピーしました」の行の高さも固定にしましょう。行の高さはあまり高くなくて、文字の上下の余白も同じくらいがいいです。

キーボード操作に対応

キー入力で操作することはできる?

ChatGPT:
はい、キー入力で操作することも可能です。以下のように、キーボードのイベントリスナーを追加して、対応するボタンのクリックイベントをトリガーするようにします。

電卓アプリの基本形完成!


さらに進化する?

やっぱり履歴機能は必須ですよね。

履歴から数値を入力できるようにしたり。

はい。後編では履歴機能も追加します!が、そこまでに結構問題が発生。ChatGPTでプログラムを作る際の問題点なども書けたらと思います。

この記事が参加している募集

#AIとやってみた

27,336件

この記事が気に入ったらサポートをしてみませんか?