【Ionic+Firebaseでアプリ開発】 データの永続化

#はじめに
[【Ionic+Firebaseでアプリ開発】お気に入り登録機能を実装する](https://qiita.com/se_fy/items/1a3a9ee38f6b54c469d1)の続きです。
前回、お気に入り機能を実装しましたが、お気に入り登録したアイテムはアプリを再起動すると消えてしまいます。
今回はアプリ内のストレージに保存することでデータを永続化します。

#Data Storageプラグインを使ってアプリ内に保存する
[Data Storage](https://ionicframework.com/jp/docs/angular/storage)プラグインを使ってアプリ内のストレージにデータを保存します。

1.`/src/app/app.module.ts`を以下のように変更してIonicStorageModuleを使えるように設定する

```app/app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';

import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';

import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';

import { InAppBrowser } from '@ionic-native/in-app-browser/ngx';

//Firebase設定情報ファイルをインポート
import { environment } from '../environments/environment';

//Firebaseを利用するためのモジュール
import { AngularFireModule } from '@angular/fire';
import { AngularFirestoreModule } from '@angular/fire/firestore';

import { IonicStorageModule } from '@ionic/storage'; //追加

@NgModule({
  declarations: [AppComponent],
  entryComponents: [],
  imports: [
    BrowserModule, 
    IonicModule.forRoot(), 
    IonicStorageModule.forRoot(), //追加
    AppRoutingModule,
    AngularFireModule.initializeApp(environment.firebase),
    AngularFirestoreModule
  ],
  providers: [
    StatusBar,
    SplashScreen,
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
    InAppBrowser
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}
```

2.以下のようにコードを修正する

```app/favorite-list/favorite-list.page.html
<ion-header>
  <ion-toolbar>
    <ion-buttons slot="start">
      <ion-back-button text="戻る" (click)="back()"></ion-back-button>　<!--変更-->
    </ion-buttons>
    <ion-title>お気に入り</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content fullscreen>
  <ion-card *ngFor="let favorite of favoriteList; let i = index" class="activated">
    <ion-item-sliding >
      <ion-item-options side="end">
        <ion-item-option (click)="deleteFavorite(i)" color="danger">削除</ion-item-option>
      </ion-item-options>
      <ion-item (click)="openPage(favorite.url)" class="activated">
      <ion-card-header>
        <ion-img src = "{{favorite.image}}" class="image"></ion-img>
      </ion-card-header>
        <ion-card-content>
            <p><font size="2">レベル：{{ favorite.level }}</font></p><br>
            <p><font size="4" color="#000000">{{ favorite.name }}</font></p>
        </ion-card-content>
      </ion-item>
    </ion-item-sliding>
  </ion-card>
</ion-content>
```

```app/favorite-list/favorite-list.page.ts
import { Component} from '@angular/core';
import { Router, ActivatedRoute, NavigationExtras} from '@angular/router';

@Component({
  selector: 'app-favorite-list',
  templateUrl: './favorite-list.page.html',
  styleUrls: ['./favorite-list.page.scss'],
})
export class FavoriteListPage {
  favoriteList = [];
  constructor(
    private activatedRoute: ActivatedRoute,
    private router: Router,
  ) {
    // homeからfavoriteListを受け取る
    this.activatedRoute.queryParams.subscribe(params => {
      this.favoriteList = JSON.parse(params.favoriteList);
    });
  }

  deleteFavorite(i) {
    this.favoriteList.splice(i,1);
  }

  back(){
    // homeにfavoriteListを渡す
    const navigationExtras: NavigationExtras = {
      queryParams:{
        favoriteList: JSON.stringify(this.favoriteList),
      }
    };
    this.router.navigate(['home'], navigationExtras);
  }
}
```

```app/home/home.page.ts
import { Component, OnInit} from '@angular/core';
import { Router, ActivatedRoute, NavigationExtras} from '@angular/router';
import { AngularFirestore } from '@angular/fire/firestore';
import { InAppBrowser } from '@ionic-native/in-app-browser/ngx';
import { ToastController} from '@ionic/angular';
import { Storage } from '@ionic/storage'; //追加

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})
export class HomePage implements OnInit{
  groundtricks = [];
  favoriteList = [];

  constructor(
    private activatedRoute: ActivatedRoute,
    private firestore: AngularFirestore,
    private inAppBrowser: InAppBrowser,
    public toastController: ToastController,
    private router: Router,
    private storage: Storage, //追加
  ) {
  }

  ngOnInit() {
    this.readGroundtrick().subscribe(data => {
      this.groundtricks = data.map(e => {
        return {
          genre: e.payload.doc.data()['genre'],
          image: e.payload.doc.data()['image'],
          level: e.payload.doc.data()['level'],
          rotation: e.payload.doc.data()['rotation'],
          name: e.payload.doc.data()['name'],
          url: e.payload.doc.data()['url'],
        };
      });
    });
    // ストレージのfavoriteListを取得する
    this.storage.get('favoriteList').then((val) => {
      this.favoriteList = val;
    });
  }

  ionViewWillEnter() {
    // favorite-listからfavoriteListを受け取る
    this.activatedRoute.queryParams.subscribe(params => {
      this.favoriteList = JSON.parse(params.favoriteList);
    });
  }

  async favorite(item) {
    const toast = await this.toastController.create({
      color: 'dark',
      duration: 2000,
      message: 'お気に入りに登録しました。'
    });
    await toast.present();
    this.favoriteList.push(item);
    // favoriteListをストレージに登録する
    this.storage.set('favoriteList', this.favoriteList);
  } 

  presentFavorite(){
    // ストレージのfavoriteListを取得する
    this.storage.get('favoriteList').then((val) => {
      this.favoriteList = val;
    });
    //favorite-listにfavoriteListを渡す
    const navigationExtras: NavigationExtras = {
      queryParams:{
        favoriteList: JSON.stringify(this.favoriteList),
      }
    };
    this.router.navigate(['favorite-list'], navigationExtras);
  }

  openPage(url){
    this.inAppBrowser.create(url);
  }

  readGroundtrick() {
    return this.firestore.collection('groundtrick').snapshotChanges();
  }
}
```

#おわりに
上記の実装でiOS端末でデータが永続化されていることが確認できました。
FireStoreに保存する方法も検討しましたが、今回はアプリのストレージで十分だったのでData Storageプラグインを使って実装しました。
アプリをアンインストールしてもデータを引き継ぎたい場合はFireStoreを使うと良いと思います。