意外と便利な「Tab型のメモアプリ」を実装してみた【Ionic】

はじめまして、ますみです！

[![自己紹介.png](https://www.umi-mori.jp/wp-content/uploads/2023/02/introduction_banner_2-2048x533.png)](https://bit.ly/banner_intro_masumi_creator_qiita)


# はじめに
この記事は、[Ionic Advent Calendar 2018](https://qiita.com/advent-calendar/2018/ionicframework)の22日目の記事です。
[ionic](https://ionicframework.com/docs/)というフレームワークの中で、実装しリリースしたメモアプリ「**Smart Memo -Tab Style-**」について紹介したいと思います。また、この記事は、コードの紹介よりも「**立案→開発→リリース**」の**約2ヶ月間の開発プロセス**についてまとめています。**みなさんの今後の開発において有益な記事**となりましたら、幸いです。

# "Smart Memo"とは？
**Smart Memo**とは、簡単に言うと、「スマートにメモを管理するタブ型のシンプルなメモアプリ」です。
<img width="200" src="https://qiita-image-store.s3.amazonaws.com/0/240280/a77e311c-fa2f-f8b4-4f3b-d39b13261086.png">
## \>>ターゲット / Target
「*メモがすごく溜まりがち！*」
「*メモを整理する時間がない...。*」
などという方々のためのアプリです。

## \>>コンセプト / Concept
「**メモをスマートに管理したいが、整理する時間がなく、メモが溜まってしまうため、初めからグループを分けた状態のメモアプリ**」

「**後から整理する...**」という考えから、「**メモする時に整理する！**」という考えを取り入れました。
ワンクリックでグループを選択してから、メモを書くことによって、整理する時間を削ります。

## リンク / Link
まずはどのようなアプリかを確認していただけたら嬉しいです！

>iOS版：[【Smart Memo -Tab Style-】(iOS)](https://itunes.apple.com/gb/app/smart-memo-tab-style/id1441934860?mt=8)
Android版：[【Smart Memo -Tab Style-】(Android)](https://play.google.com/store/apps/details?id=dev.Masumi.SmartMemo)

# 大まかな流れ
大まかな流れは次の通りです。
**計画(Plan)**、**実行(Do)**、**評価(Check)**、**改善(Act)**の流れでまとめました。
実行(Do)では、Ionicというフレームワークの用語を用いているため、なんのことかはわからなくても大丈夫です。
<img src="https://qiita-image-store.s3.amazonaws.com/0/240280/72bc3cef-a818-96b4-b403-accdcf543c66.jpeg" width="800">

# Plan 〜計画〜
まずは、計画からです！
ここのプロセスは結構長い期間（2週間くらい）ずっと家や大学や移動時間などで考えて、練っていました。

## P1：コンセプト決め
コンセプトは、機能やデザインについて自分が迷った時に、原点に戻ってくるための大切な指標になります。
この際、[株式会社LITALICO](http://litalico.co.jp/)という会社のCTOの岸田さんのブログを参考にしました。
具体的には、「[サービス開発は9割が失敗する - 6つの診断パターンからみるサービス設計がうまくなるコツ（前編）](http://asagao.hatenablog.jp/entry/2016/11/30/220000)」という記事の「**ユーザ・欲求・課題・サービスの特徴**」の4つに分けて、考える方法を取り入れさせていただきました。とても参考になるブログな上、素敵な理念を持った会社なため、もしよければ、ホームページの方もご覧ください。

>LITALICO：http://litalico.co.jp/
岸田さんのブログ：http://asagao.hatenablog.jp/entry/2016/11/30/220000

結果的に、**`「メモをスマートに管理したいが、整理する時間がなく、メモが溜まってしまうため、初めからグループを分けた状態のメモアプリ」`**というコンセプトにすることにしました。このコンセプトの原点としては、**自分のメモ帳がものすごく溜まってしまっていて、それらを整理することがめんどくさくなってしまった**ことから始まりました。

## P2：コアな機能の抽出
さて、コンセプトも決まったところで、まずは一度「コアな機能」を書き出してみました！
コアな機能とは、このアプリに「必要不可欠な機能」と定義しました。

#### \>>Smart Memoのコアな機能
- メモをする機能
- タブを移動できる機能
- 自動保存してくれる機能
- （タブの名前をカスタマイズできる機能）

(最後の機能は絶対必要ではないが、*しっかりと整理したいユーザーをターゲットにしている*ため、コアな機能に含めました。）

## P3：ペーパープロトタイプの作成

「さぁー、いよいよコーディング！」と思いきや、まだ "Plan" のプロセスは終わりません。
続いて、**ペーパープロトタイプ**という、紙の上でのプロトタイプを作りました。

以下のような感じになりました。
<img width="500" src="https://qiita-image-store.s3.amazonaws.com/0/240280/b4aeb196-2ec2-9dd5-9ff4-c6bef756df80.jpeg">

だいぶざっくりしていますね笑
あまり良くない例な気ますが、参考程度にご覧ください。

## P4：Todoリストの作成
コンセプト / コアな機能 / ペーパープロトタイプができたところで、やらなくてはいけないことのリストを作りました。
この時、それぞれの工程が**どれほど時間がかかるのか**、**どの順番で行うのか**についてもなるべく細かく決めました。

これくらいの計画を立てれば、十分なのではないでしょうか？
計画に時間をかけすぎて、モチベーションが下がってしまう可能性を考慮すると、個人的にはこれくらいが最適な詰め具合だと思います！

# Do 〜実行〜
続いては、ついに実装の部分です！
Ionicエンジニアにとっては、有益な情報があることを期待しますが、「*Ionicというフレームワークをそもそも触ったことがない！*」、「*そもそもIonicってなんぞや？*」という方々も大勢いらっしゃると思います。なるべく砕いて、説明することを心がけますが、もしも必要ない場合は、そこまで重要ではないので、**PDCAのDの部分で実装しているんだなくらいに捉えて、読み飛ばしてもらっても大丈夫です！**

## D1：テンプレートの作成 (Tab機能)
まずは、Ionicで、`blank`のテンプレートページを作成しました。
具体的には、以下のような手順をTerminalで踏みました。
（**`Ionic3`のテンプレートを使用。**）

```terminal:D1
$ ionic start
? Try Ionic 4? No
? Project name: smartMemo

? Starter template:
  tabs     | A starting project with a simple tabbed interface
❯ blank    | A blank starter project
  sidemenu | A starting project with a side menu with navigation in the content area
  super    | A starting project complete with pre-built pages, providers and best practi
ces for Ionic development.
  tutorial | A tutorial based project that goes along with the Ionic documentation
  aws      | AWS Mobile Hub Starter

? Install the free Ionic Appflow SDK and connect your app? No
```

`Tab`のテンプレートから始めてもよかったのですが、5タブにしたかったため、美しく作るために`blank`から始めました。

続いて、[Tabsの作成・追加【Ionic】](https://qiita.com/umi_mori/items/a16bc12f25601d92de01)の記事にそって、タブを作成しました。

ここまでの作業で、以下のような5タブのアプリができました。
<img width="500" alt="スクリーンショット 2018-10-30 14.50.28.png" src="https://qiita-image-store.s3.amazonaws.com/0/240280/ff48f622-2eb6-2e47-06f0-4503432e8d1e.png">

## D2：メモ機能の実装 (text-area)
ここでは、各タブのhtmlデータに`<ion-textarea>`を追加し、メモを書ける部分を実装した。
具体的には次のようなコードです。

```html:src/pages/tab-a/tab-a.html
<ion-content padding no-bounce>
  <ion-textarea rows="30" placeholder="メモを入力"></ion-textarea>
</ion-content>
```

また、タブのアイコンをオリジナルのアイコンに変え、次のようになりました。
<img width="300" alt="Screen Shot 2018-12-22 at 1.11.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/240280/e258bd0b-507a-2d7d-eb06-84f223067766.png">

## D3：自動保存機能の実装 (localStorage)
続いて、アプリを終了した後も、データがしっかりと残るように端末内のローカルのストレージに自動保存される機能を実装しました。
具体的には、まずhtmld側に次のようなコードを書きました。

`html:src/pages/tab-a/tab-a.html
<ion-content padding no-bounce>
  <ion-textarea rows="30" [(ngModel)]="MemoA" placeholder="メモを入力" value={{MemoA}} (ionChange)="saveMemo()"></ion-textarea>
</ion-content>
`
コードの内容としては、`(ionChange)="saveMemo()"`という部分で、「もしもテキストボックス内の文字が変更された時に、`saveMemo()`という関数を実行する」ようにしました。また、その時入力されたデータを関数に共有できるように`[(ngModel)]="MemoA"`を書きました。`value={{MemoA}}`では、テキストエリア内にストレージの中の文字が維持されるような働きを行っています。

一方、typescript側では次のように書きました。

`ts:src/pages/tab-a/tab-a.ts
import { Component } from '@angular/core';
import { IonicPage, NavController, NavParams} from 'ionic-angular';

@IonicPage()
@Component({
  selector: 'page-tab-a',
  templateUrl: 'tab-a.html',
})

export class TabAPage {
  constructor(
    public navCtrl: NavController,
    public navParams: NavParams) {
  }

  MemoA: string;

  saveMemo(){
    localStorage.setItem('MemoA', JSON.stringify(this.MemoA));
  }

  ionViewWillEnter(){
    if(localStorage.getItem('MemoA')!=="undefined"){
      this.MemoA = JSON.parse(localStorage.getItem('MemoA'));
    }else{
      this.MemoA = "";
      localStorage.setItem('MemoA', JSON.stringify(this.MemoA));
  }
}
`
このスクリプトでは、簡単にいうと、画面がロードする時に、ローカルストレージ内に、`MemoA`という名前のデータがあるかをチェックしています。（`if(localStorage.getItem('MemoA')!=="undefined")`） そして、もしもあった場合は、MemoAというスクリプト内の変数に代入するという内容です。（`this.MemoA = JSON.parse(localStorage.getItem('MemoA'));`） この時、もしもローカルストレージ内にそのデータがない場合は、初期化するようにしています。

## D4：タブ名変更機能の実装 (Popover)
タブ名を変更するためのナビゲーションをまず作りました。今回は、Ionic3に搭載されている[**`PopoverController`**](https://ionicframework.com/docs/api/components/popover/PopoverController/)という機能を使いました。詳しくは、docsを参考にしてください。【[PopoverController](https://ionicframework.com/docs/api/components/popover/PopoverController/)】

<img width="300" alt="Screen Shot 2018-12-22 at 1.31.40.png" src="https://qiita-image-store.s3.amazonaws.com/0/240280/f36f9ad2-9a19-e261-d3fe-de3da0509c4a.png">

## D5：Privacy Policyの作成 (GitHub-Pages)
簡易的ではありますが、Privacy PolicyがiOSの審査に必須となったため、Privacy Policyと利用規約（念のため）を作成し、GitHub-Pagesを用いて、アップしました。

>**GitHub-Pages**
概要：自分のGitHub内にサーバーを立ち上げて、htmlデータを公開する。
リンク：https://pages.github.com/

## D6：ブラウザジャンプの実装 (InAppBrowser)
続いて、アプリ内のボタンからSafariなどのブラウザへジャンプできる機能を実装しました。
この機能をつける過程で、ブラウザ上のローカルサーバーでうまくいっても、ネイティブだとうまくいかないことがあり、意外と苦戦しました。最終的に、たどり着いた方法が**`InAppBrowser`**という機能でした。【[InAppBrowser](https://ionicframework.com/docs/native/in-app-browser/)】

## D7：広告バナーの導入 (nend)
これで、ほぼコアな機能は全て実装できました！
ここで、少し収益化を考えたいと思います。
**開発する過程でかかるお金は意外とバカにならない**ため、少しでも収益を上げたいところだと思います。
しかし、**スピード感を持って、リリースすることも大切**です。
そのため、Ionicで高速で収益化する方法でとりあえず実装しました。（下記参照）

>**10秒のコーディングで収益化する方法【Ionic】**
リンク：https://qiita.com/umi_mori/items/8ba84fa33f8fb8d6dd0b

以上のことを全て実装すると最終的に以下のような感じになります！
<img width="300" alt="S__49307659.jpg" src="https://qiita-image-store.s3.amazonaws.com/0/240280/9bd72314-fa4d-0c54-7db8-a01973f9c9ff.jpeg">

## D8：リリース (App Store)
最終的に、アプリ自体は完成したため、あとは、リリースですね。しかし、**正直意外とここが鬼門だったりします。**初めての場合は特にわからないことばかりで難しいと思います。ここでは説明は省略しますが、唯一言えることは、**「誰にも相談せず自分だけの力で頑張ろうとしない方がいい」**時もあるということです。XCode周りの記事は豊富にネットにありますし、調べて出てきたやり方でも解消しない場合は、周りの知人に聞くことも大切だと思います。もしも周りに通じる人がいなく、どうしようもなければ、下記のtwitterアカウントにDM気軽に投げてください。可能な限りですが、対応します。

>**クリエイティブ・テクノロジー【twitter】**
リンク：https://twitter.com/creative___tech

# Check 〜評価〜
いよいよ、実装も終わり、リリースされました！
「さぁー、次のアプリを作るか！」となってしまってはもったいないです！
**ここからの「[グロースハック](https://ferret-plus.com/1053)」の作業も非常に楽しい**ので、ぜひ行ってみてください。

>**グロースハックとは？**
意味：ユーザーから得た製品やサービスについてのデータを分析し、改善して マーケティングの課題を解決していく手法（ferretより）
リンク：https://ferret-plus.com/1053

## C1：ヒアリング(友達など)
まずは、何と言っても、**周りの人から直接意見を聞くことがとても手っ取り早い**です。
*レビューなどは、ある程度貯まるまでは見ることができない*ため、スピード感を失ってしまいます。
特に、致命的なバグや客観的な意見を初期の段階で得られると、ユーザーの定着につながるため大切だと考えられます。

僕が友達からヒアリングした意見は具体的には、次の通りです。
- 入力する時に、ガタガタする
- 入力を完了した後に、キーボードをしまうためのボタンがあったら便利

## C2：レビューの確認
レビューがまだ不十分なため、レビューの情報からアプリを評価することはまだできていません。

## C3：コンセプトの見直し
ここで、大切なプロセスとして、**コンセプトに振り返る**ことがあると思います。
- 「**アプリがコンセプトに沿っているか？**」
- 「**そもそもコンセプトは的を射ているか？**」
- 「**ターゲットとしているユーザーが使い続けているイメージが湧くか？**」
- 「**コンセプトに不必要な機能はないか？**」
などを念頭に改めて検討し直しました。

## C4：Todoリストの再作成
以上のアプリの評価（check）を経て、Update版のリリースに向けてTodoリストを再び検討し直しました。
その結果次のようなアップデートを行うことにしました。
- 完了ボタンの実装 【ヒアリング】
- 入力時のガタガタのバグ 【ヒアリング】
- 全テキストをコピーする機能 【ユーザー視点】
- 多言語化 【マネタイズ面】
- Pro版のリリース 【マネタイズ面】
- その他のバグ 【バグ】

# Act 〜改善〜
致命的なバグから順番にスピード感を持って改善することが大切だと考えられます。
では、最後に、改善のプロセスにいきましょう。

## A1：Update優先度の整理
まずは優先度を決めるところからです。時間は有限なためん、どのアップデートが最も重要かを見極めましょう。特に、致命的なバグはなるべく早く取り除く必要があります。

Smart Memoの場合は、次のような優先順位にしました。（実際には、実装の手軽さなどから、多少前後はしました。）

1. 致命的なバグ 【バグ】
2. 入力時のガタガタのバグ 【ヒアリング】
3. 完了ボタンの実装 【ヒアリング】
4. 細かなバグ 【バグ】
5. 多言語化 【マネタイズ面】
6. Pro版のリリース 【マネタイズ面】
7. 全テキストをコピーする機能 【ユーザー視点】
8. Android版のリリース【マネタイズ面】

このうち、致命的なバグとして、「タブが押せなくなるバグ」などがありました。
また、今回はiOS版のリリースの方が慣れていたため先に始めましたが、**Android版の方がリリースに要する時間が短く（iOSアプリはしっかりとした審査があるため）、PDCAを回しやすいという点から、Androidでファーストリリースをし、90%近くまで完成したらiOS版でリリースするという手法**もあるらしいです。

## A2：Update機能の実装
続いて、以上のTodoを順番に消化していきました。
この時、データ消失を防ぐために、**各バージョンでバックアップをしっかりと取る**ことはお忘れなく！
Gitをつかった管理でもいいと思いますし、zipファイルをクラウドに上げていく方法でもどちらでもいいと思います。

また、具体的なアップデートの実装方法は次の通りです。

|項目|実装方法|
|:---:|:---:|
|タブが押せなくなるバグ|`localStorage`が`undefined`になっていることが原因だったため、その条件を追加して実装（D3を参照）|
|入力時のガタガタ|`<ion-textarea>`が原因だったため、`<textarea>`を用いて実装|
|完了ボタン|Ionic Nativeの**[【Keyboard】](https://ionicframework.com/docs/native/keyboard/)**を利用|
|多言語化|Ionic3の**[【ngx-translate】](https://ionicframework.com/docs/developer-resources/ng2-translate/)**を利用。|
|Pro版のリリース|広告の削除 / 追加機能（コピー機能）|
|コピー機能|Ionic Nativeの**[【Clipboard】](https://ionicframework.com/docs/native/clipboard/)**を利用。|

## A3：リリース(Update版)
ここで、注意することとして、**`config.xml`データ内のversionをあげること**にのみ注意すれば、従来通りの方法で問題ありません。

## A4：C1〜A3を繰り返す
あとは、ある程度の形なるまでのC1〜A3までのサイクルを繰り返します。

# 追記①：Pro版について / Pro Edition
一番**安い設定額**で、Pro版をリリースしました。
一度課金すれば、**ずっと広告バナーがない**上、**随時新しい機能が追加されていく**ため、ぜひご検討くださいb

>iOS版：[【Smart Memo Pro -Tab Style-】](https://itunes.apple.com/us/app/smart-memo-pro-tab-style/id1446116203?mt=8)
Android版：[【Smart Memo Pro -Tab Style-】](https://play.google.com/store/apps/details?id=dev.Masumi.SmartMemoPro)
<img width="200" src="https://qiita-image-store.s3.amazonaws.com/0/240280/a916e38f-6069-a2ed-7eb1-a76f31a54ee3.png">

# 最後に
最後まで読んでくださり、ありがとうございました！
いかがだったでしょうか？

この記事を通して、少しでもあなたの学びに役立てば幸いです！

:::note info
【仕事の相談はこちら】
お仕事の相談のある方は、下記のフォームよりお気軽にご相談ください。

[問い合わせフォームはこちら](https://forms.gle/G5g1SJ7BBZw7oXYA7)

もしもメールでの問い合わせの方がよろしければ、下記のメールアドレスへご連絡ください。

info*galirage.com（*を@に変えてご送付ください）

🎁 「生成AI活用の無料相談券」もしくは「生成AIの社内ガイドライン（無料PDF）」を『公式LINE』で配布中 🎁
『生成AIを業務に活用したいけど、どうしたらいいかわからない』といった声を多くいただきます。

Galirageでは公式LINEにて、チャットやオンライン会議で「完全個別の生成AI活用無料相談会」を実施しております！
（期間限定で実施しているため、ご興味ある方はお早めに以下のLINE公式アカウントをご登録ください^^）
https://lin.ee/rvz6lMN

※ 予告なく、キャンペーンを終了する可能性がございますが、ご了承ください。

【業務内容】
具体的には、以下のお仕事を中心に受け付けております！（[詳しくはこちら](https://galirage.notion.site/Galirage-AI-c2f3945fafb0433d8d2fd03e56927fd8)）
1. 受託開発（例：生成AIを使った社内システムの開発）
2. コンサルティング（例：技術戦略のアドバイス）
3. 講演（例：社内研修、イベント登壇）

※ 特に「生成AIを使ったシステム開発のご依頼」が多く、ご好評いただいております。

【これまでの相談事例】
以下のようなご相談が多くあります。

🔑 機密情報を漏洩させないための、生成AIのシステム構築をお願いしたい。
🤖 自社データを用いたFAQチャットボットの作り方を知りたい。
💡 ChatGPTを、自分たちの事業にどのように活かせるか、アドバイスやアイデアが欲しい。
:::
# おまけ
エンジニアの仲間（データサイエンティストも含む）を増やしたいため、公式LINEを始めました🎉

「**一緒に仕事をしてくれる方**」「**友だちとして仲良くしてくれる方**」は、友だち追加をしていただけますと嬉しいです！（仲良くなった人たちを集めて、「ボードゲーム会」や「ハッカソン」や「もくもく会」もやりたいなと考えています😆）

とはいえ、みなさんにもメリットがないと申し訳ないので、特典を用意しました！

友だち追加後に、アンケートに回答してくれた方へ「**エンジニア図鑑（職種20選）**」のPDFをお送りします◎

https://lin.ee/hFUN4TL

[![](https://www.umi-mori.jp/wp-content/uploads/2023/10/line_banner_v2.png)](https://lin.ee/hFUN4TL)