目的

UIWebViewのDeprecated対応はもう必須となりました。

ということで、
アプリ内で使われているUIWebViewをWKWebViewに対応したところWebView内で利用していたローカル画像や動画が表示されなくなったのでその対応メモです。  

ちなみにWebViewでhtmnl言語のimgタグなどで画像を利用している状況です。

環境

  • Xcode Version 12.5
  • Swift 5

参照サイト

DevelopersIO [Swift] そう、あの頃の僕はただWKWebViewにアプリ内に保存された画像ファイルを表示させたかったんだ

対応の前に

そもそも画像を表示するのになんでWebViewでhtmlなんか使うんや!とのツッコミがあります。

私が使ったのではなく、受け継いだ案件で利用していました。

どうやら一時期、アニメーションGIFをアプリで利用する場合、UIWebViewでhtmlで表現する手法が流行った!?ようです。

個人的見解で、真相は不明ですが、
特にObjective-C世代のアプリでは、アニメーションGIFを手軽に導入する術は無かったのかもしれないです。

対応メモ

対応策は3つあると思いました。

  • 画像はBASE64形式に直して、htmlで使い続ける
  • アニメーションGIFに対応した、ライブラリを利用する
  • アニメーションGIFを画像に分解して、UIImageの配列に入れてタイマーで回す

画像はBASE64形式に直して、htmlで使い続ける

元からhtmlを使っていたのであれば、この手法が一番既存アプリへの影響度は少ないと思いますが。
ちょっと辛い面もあります(後述)。

参照サイトの通り、セキュリティの観点からかWKWebViewではhtmlで読み込むファイルは素で利用できないようです。
なんで表示されないかずっと悩んでいたので、参照サイトには助かりました。

具体的なプログラムは参照先を御覧ください。

Base64化
//ファイルのパスを求める
URL形式でしたらpathとかlastPathComponentオプションを利用して求められるかも

//URL形式からData形式に変換
FileManagerを使うかNSDataのcontentsOfFIleを利用する

//Base64形式にする
base64EncodedStringを使う

//ファイルの拡張子を取得する
URL形式でしたらpathExtensionとかでしょうか
上記で出来たBase64形式データをimgタグやvideoタグにぶちこみます。

以下の
「拡張子」 にはアニメーションGIFでしたらgif、動画でしたらmp4とかでしょうか。
↑のようにコマンドで取得するようにしました。
*は自分の環境では使えませんでした。
「Base64形式ファイルデータ」 に、↑のbase64EncodedStringで返ってきた変数を入れます。

タグでbase64形式を利用する方法
<img src='data:image/「拡張子」/base64,Base64形式ファイルデータ」' ... />
<video src='data:video/「拡張子」;base64,Base64形式ファイルデータ」' ... />
上記で表示されるようになりましたが、自分の環境では、
オブジェクトの表示タイミングによってなのか、CSSがうまく読み込まれないという結構大きな問題がありました。
画面中央に配置とかができなく、結局解決せずで、
WebViewのサイズを大きくしたりとかで無理やり対応するしか無いと思います。

アニメーションGIFに対応した、ライブラリを利用する

SwiftGif

LBGIFImage
ライブラリを使ってUIImageViewやUIImageに変換して、表示させます。
個人的にはこの対応が一番手軽でしたが、上記ライブラリが最近更新されなくなっているので、今後のOSアップデートによる対応必要性が不安ですね。

アニメーションGIFを画像に分解して、UIImageの配列に入れてタイマーで回す

アニメーションGIFはFinderアプリで1枚ずつ画像で確認でき、保存できると思うので、分解します。
アプリでUIImageの配列を作り1枚ずつ入れ込みます。

画面表示用のUIImageViewを作り、初期は uiImageView.image = uiImageList[0]を設定して、NSTimerを使って、一定時間ごとにUIImageをカウントアップさせていくものです。

NSTimerで呼ぶ関数は以下のようなカンジでしょうか。

NSTimerで呼ばれる
@objc
func timerXX() {
    if uiImageList <= 画像数 {
        imagecount = 0
    }
    uiImageView.image = uiImageList[imagecount]
    imagecount += 1
}
自分は普通のやり方だと思うのですが、その道の人にとっては外道なのかもしれません。
NSTimerって前はviewDidUnloadとかでinvalidateとかnilにしないとクラッシュしていた記憶があり。。

そんなの使うなや!とか言う人が本当にいるんですよね^^;

対応メモは以上です。