2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

開発中に画像が消失?Expoのファイルシステムと相対パスの重要性

Posted at

はじめに

対象読者

ReactNative、Expoでアプリ開発を行っている人
expo-file-systemを使って画像データをローカルにキャッシュしたい人
npm run iosなどでアプリを立ち上げ直すと画像が表示されず困っている人

読者への思い

Expoでアプリ開発中に画像の保存や表示でかなり詰まったので同じ罠にハマっている人がいたらこれ見て解決してください!

その時の現状と問題点

私はReactNativeExpoFirebaseを使ってアプリを開発しており、アプリとFirebase間での通信をなるべく減らすべく、ReactNativeのAsyncStorageとExpoのexpo-file-systemを使って画像をキャッシュをローカルに作れるようにしようとしていました。

システムの概要はこちらになります。
無題のプレゼンテーション (1).png

  1. FirebaseのStorageに画像を保存しており、そのファイルパスをFireStoreに保存しています。
  2. アプリはFireStoreからStorageのファイルパスを取得し、Storageからその画像ファイルをダウンロードします。
  3. 一度取得した画像はキャッシュとして使い回したいので、expo-file-systemを使用して保存し、expo-file-systemのファイルパスをAsyncStorageで保存していました。

実際に最初にダウンロードし、表示させた結果がこちら

Simulator Screenshot - iPhone 15 Pro Max - 2023-11-15 at 16.09.06.png

これはリロード(rコマンド)をしても変わらず表示されて期待通りです。

しかし、ctrl+cでアプリを止め、再度npm run iosでアプリを立ち上げた際に、以下のように画像が表示されなくなってしまいます。

Simulator Screenshot - iPhone 15 Pro Max - 2023-11-15 at 16.08.25.png

この原因について調べることにしました。

解決法

問題を調べていく中で、画像のファイルパスは正しく保存されており、特にエラーも出ていないことから、expo-file-systemから画像をうまく取得できていないことがわかりました。
そこで調べていくと、、、

こちらの記事に辿り着きました。

結論として、iOSシステムはビルド間でパスが継続することを保証していないため、相対パスを使用することで、異なるアプリビルドやバージョン間でファイルへのアクセスを維持することができるとのことでした。

私はexpo-file-systemの絶対パスをAsyncStorageに保存してそれをImageのsourceに入れていたため、npm run iosで立ち上げ直すと画像の保存されているパスとは別のパスにアクセスしてしまい、取得できていなかったのです。

使える関数等

ここでは上記の問題を解決するためのコードなどを紹介します。

getDownloadImage.js
import * as FileSystem from 'expo-file-system';

export default function getDownloadedImageUri(relativePath) {
  return `${FileSystem.documentDirectory}${relativePath}`;
}

こちらは相対パスから画像を取得する関数です。相対パスを引数にFileSystemのパスへ変換します。

ccreateImagesDirectory.js
import * as FileSystem from 'expo-file-system';

export default async function createImagesDirectory() {
  const imagesDir = `${FileSystem.documentDirectory}images`;

  const dirInfo = await FileSystem.getInfoAsync(imagesDir);
  if (!dirInfo.exists) {
    await FileSystem.makeDirectoryAsync(imagesDir, { intermediates: true });
  }
}

こちらはFileSystem内にimagesというディレクトリを作成する関数です。こちらを使いimagesの直下に保存するようにすると良いでしょう。

await createImagesDirectory();
const relativePath = `images/${filename}`;
const downloadDest = `${FileSystem.documentDirectory}${relativePath}`;

このようにすることで、画像の保存も取得も可能になります。

まとめ

画像の保存には相対パスが大事!!!

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?