SwiftUIのImageは Image(“chincoteague”)と書けばプロジェクト内「Assets.xcassets」に配置した“chincoteague”画像を利用することができます。
しかし、Assetsに配置した場合インターネットなどから 動的にアプリ内画像変更などができません。そういった場合に対処するため、Webサーバーに配置された画像をアプリ内のImageで表示させる方法です。
Imageにはinit(uiImage: UIImage)がありますが、ここにWebサーバーから取得した画像データを埋めれば実現できます。Webサーバーのデータ取得方法は前回SwiftUIからWebサーバー文字列を取得する方法を書いていますが、この方法と同じくURLSessionを使います。
URLSession.shared.dataTask(with: URL(string: "https://mojeld.com/img/charleyrivers.jpg")!) { d1, _, _ in
}
dataTask()にURLを入れると、{ d1, _, _ in }の中のd1にデータが入ります。取得後UIImage()にd1を設定すれば画像データがUIImage()に入ります。
let d2 = UIImage(data: d1)
Webサーバーからの画像取得からUIImageに設定するまでの動作をObservableObject継承したクラスにまとめます。
class TURLImage: ObservableObject {
enum TNetStatus { case none; case standby; case successfll }
@Published var netStatus: TNetStatus = .none
@Published var img : UIImage = UIImage()
func getImg(_ urlStr: String) -> Void {
guard let url1 = URL(string: urlStr) else { return }
netStatus = .standby
URLSession.shared.dataTask(with: url1) { data, _, _ in
guard let d1 = data,
let d2 = UIImage(data: d1, scale: 5) else {
return
}
DispatchQueue.main.asyncAfter(deadline: .now() + 1 ) {
self.netStatus = .successfll
self.img = d2
}
}.resume()
}
}
TURLImageという名称のクラスを作成しました。そこにはTNetStatusというステータスを示すenumとUIImageを@Publishedに置いています。@Publishedに配置した場合View側でクラス内の変更を知ることができます。配置したUIImageのscaleを「5」に設定しています。これたぶんscale 1/5ということだと思います。クラス内のvar img : UIImageの更新は、DispatchQueue.main.asyncAfter()を使って1秒間待ってから処理しています。これは読込み中描画を1秒以上表示したかったからです。
つぎは、View側の処理です。iOSアプリ画面のボタンを押すと「読み込み中…」を表示しWebサーバーからデータを取得するまでのコードが下記です。
struct TNetImage: View {
@State var uStr: String
@ObservedObject var urlImage: TURLImage = TURLImage()
var body: some View {
VStack {
if ( self.urlImage.netStatus == TURLImage.TNetStatus.successfll ) {
Image(uiImage: self.urlImage.img)
} else if ( self.urlImage.netStatus == TURLImage.TNetStatus.standby) {
Text("読み込み中…")
}
Button("Button1", action: {
self.urlImage.getImg(self.uStr)
} )
Spacer()
}
}
}
TNetImageというViewを作成し、 「Button1」を押したあと「読み込み中…」が表示されWebサーバーからの画像データ取得完了後Image表示に切り替わります。
ボタンを押すと「読み込み中が表示され」読み込み完了後Image表示される