image
在
SwiftUI
中,通過Image
來展示圖片,例如:
Image("touxiang")
Image(systemName: "arkit")
.foregroundColor(.orange)
.font(.system(size: 48))
Image("touxiang")
.resizable()
.aspectRatio(contentMode: .fit)
Image(uiImage: UIImage(named: "touxiang"))
.resizable()
.frame(width: 50, height: 50)
以上都是使用Image
加載本地圖片資源,但是SwiftUI
中的Image
沒有提供直接加載URL
方式的圖片顯示,那么如何在SwiftUI
中讓Image
加載網(wǎng)絡(luò)圖片呢,可以采用異步加載網(wǎng)絡(luò)圖片數(shù)據(jù),由data
轉(zhuǎn)換成UIimage
,再給Image
展示
struct ContentView : View {
@State private var remoteImage : UIImage? = nil
let placeholderOne = UIImage(named: "Picture")
var body: some View {
Image(uiImage: self.remoteImage ?? placeholderOne!)
.onAppear(perform: fetchRemoteImage)
}
func fetchRemoteImage()
{
guard let url = URL(string: "http://hdjc8.com/images/logo.png") else { return }
URLSession.shared.dataTask(with: url){ (data, response, error) in
if let image = UIImage(data: data!){
self.remoteImage = image
}
else{
print(error ?? "")
}
}.resume()
}
}
但是這種異步加載圖片的方式在Widget
中卻失效了,Image
顯示不了圖片。
在TimelineProvider
的getTimeline
中completion(timeline)
執(zhí)行完之后,不再支持圖片的異步回調(diào)了,所以必須在數(shù)據(jù)請求回來的處理中采用同步方式,將圖片的data
獲取,轉(zhuǎn)換成UIimage
,在賦值給Image
展示。
接下里給iOS14 Widget小組件開發(fā)實踐2——自定義Widget里搭建的古詩視圖增加一個網(wǎng)絡(luò)封面圖片顯示,效果如下:
根據(jù)上面說的,既然異步加載圖片不行了,必須在數(shù)據(jù)請求回來的處理中采用同步方式,將圖片的
data
獲取,轉(zhuǎn)換成UIimage
。那么我們先來在Poetry
里面增加一個UIimage
參數(shù):
struct Poetry {
let content: String // 內(nèi)容
let origin: String // 名字
let author: String // 作者
var icon: UIImage? = UIImage(named: "touxiang") // 圖片
}
因為這個免費的API
接口沒有返回圖片封面數(shù)據(jù),所以就自己網(wǎng)上找個圖片用來測試。關(guān)于圖片請求的時機,這里我是將它放在了API
接口回調(diào)后處理json
轉(zhuǎn)model
的這一步:
static func poetryFromJson(fromData data: Data) -> Poetry {
......
}
static func modelFromJson(fromData data: Data) -> Poetry {
let json = try! JSONSerialization.jsonObject(with: data, options: []) as! [String: Any]
//因為免費接口請求頻率問題,如果太頻繁了,請求可能失敗,這里做下處理,放置crash
guard let data = json["data"] as? [String: Any] else {
return Poetry(content: "詩詞加載失敗,請稍微再試!", origin: "耐依福", author: "佚名")
}
let content = data["content"] as! String
let origin = data["origin"] as! String
let author = data["author"] as! String
//這里加入對圖片進行同步請求
var image: UIImage? = nil
if let iamgeData = try? Data(contentsOf: URL(string: "https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1058052610,2039041423&fm=26&gp=0.jpg")!) {
image = UIImage(data: iamgeData)
}
return Poetry(content: content, origin: origin, author: author, icon: image)
}
最后在給PoetryWidgetView
布局界面:
struct PoetryWidgetView : View {
let entry: PoetryEntry
var body: some View {
HStack(content: {
Image(uiImage: entry.poetry.icon!)
.resizable()
.frame(width: 70, height: 70)
VStack(alignment: .leading, spacing: 4) {
Text(entry.poetry.origin)
.font(.system(size: 20))
.fontWeight(.bold)
Text(entry.poetry.author)
.font(.system(size: 16))
Text(entry.poetry.content)
.font(.system(size: 18))
}
})
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .leading)
.padding()
.background(LinearGradient(gradient: Gradient(colors: [.init(red: 144 / 255.0, green: 252 / 255.0, blue: 231 / 255.0), .init(red: 50 / 204, green: 188 / 255.0, blue: 231 / 255.0)]), startPoint: .topLeading, endPoint: .bottomTrailing))
}
}
參考資料
https://github.com/fzhlee/SwiftUI-Guide#20Image-Web
SwitUI-實現(xiàn)URL圖片顯示