距离上一篇小组件开发过去了好久了,哎…,一直没来得及补充,事情有点多,不过还好都过去了.那今天我们就来看下小组件开发二,之小组件的图片加载.
- 上一篇:iOS14 小组件开发1
上一篇我们完成了小组件的创建,数据构建,网络请求,以及数据的刷新.接下来我们来看下图片加载.
我们在写App的时候,我们的网络请求都是异步请求,图片也是一样的.但是在小组件里面不行.没有图片的异步加载,或者是回调到主线程刷新图片.小组件的图片加载和数据加载一样必须通过Timeline,来刷新.也就是说小组件的刷新只能靠timeline.也就是时间线. 下面来看代码(接上一篇文章): 我们在view里面的添加一个ImageV,放到视图的左边.
//:展示View
struct tiangoWidgetEntryView : View {
let placehoulder = UIImage(named: "download")!
//:拿到保存的数据
var entry: PoetryEntry
//:构建UI
var body: some View {
HStack{
Image(uiImage: UIImage(data: entry.imgData) ?? placehoulder)
.frame(width: 90, height: 90)
VStack(alignment: .leading, spacing: 4) {
Text(entry.poetry.origin)
.font(.system(size: 18))
.fontWeight(.bold)
Text(entry.poetry.content)
.font(.system(size: 18))
.fontWeight(.bold)
}
.frame(minWidth: 0, idealWidth: 0, maxWidth: .infinity, minHeight: 0, idealHeight: 0, maxHeight: .infinity, alignment: .leading)
.padding()
.background(LinearGradient(gradient: Gradient(colors: [.init(red: 254 / 255.0, green: 211 / 255.0, blue: 0 / 255.0)]), startPoint: .topLeading, endPoint: .bottomTrailing))
}
}
}
然后设置默认图.然后运行就会看到一个image.那么现在我们要给我们的image 赋值网络数据,加载网络图片.刚刚说了只能依赖TimeLine来刷新当前的视图.那么我们来看TimeLine
这里有一个iOS交流圈:891 488 181 可以来了解,分享BAT,阿里面试题、面试经验,讨论技术,裙里资料直接下载就行, 大家一起交流学习!
- 现在的TimeLine 长这样
struct PoetryProvider:TimelineProvider {
//:占位
func placeholder(in context: Context) -> PoetryEntry {
let poetry = Poetry(content: "我要傍近你", origin: "方不至于难过")
//:记住这里返回的对象都是 Entry 所以要拼接Model
return PoetryEntry(date: Date(), poetry: poetry,imgData: Data.init())
}
//:截图
func getSnapshot(in context: Context, completion: @escaping (PoetryEntry) -> Void) {
let poetry = Poetry(content: "我要傍近你", origin: "方不至于难过")
let entry = PoetryEntry(date: Date(), poetry: poetry,imgData: Data.init())
//:这里使用 completion 进行回调
completion(entry)
}
//:网络数据请求
func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> Void) {
//:获取当前时间 进来就是最新的数据 保存当前的时间 一次为时间点 计时 计算下一次更新的时间
let currentDate = Date()
//:下一次更新的时间以分钟为单位,间隔是每五分钟请求一次数据
let updateDate = Calendar.current.date(byAdding: .minute, value: 5, to: currentDate)
//:请求网络数据
var poeEtry = PoetryEntry(date: Date(), poetry: Poetry(content: "我要傍近你", origin: "方不至于难过"), imgData: Data.init())
PoetryRquest.request { (reslut) in
let poetry: Poetry
if case .success(let res) = reslut {
poetry = res
}else{
poetry = Poetry(content: "我要傍近你", origin: "方不至于难过")
}
//:这里返回的还是PoetryEntry 但是需要带着时间线
poeEtry = PoetryEntry(date: updateDate!, poetry: poetry,imgData: Data.init())
PoetryRquest.fetchRemoteImage(urlString: "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1607536244259&di=05bbaed6686b95b208a709596b6199ae&imgtype=0&src=http%3A%2F%2Fimgsrc.baidu.com%2Fforum%2Fw%3D580%2Fsign%3Dabbf8f972d738bd4c421b239918b876c%2F8169ca8065380cd7e02852a7a244ad3459828159.jpg") { (result) in
let imgData :Data
if case .success(let res) = result {
imgData = res
}else{
imgData = Data.init()
}
poeEtry.imgData = imgData
let timeLine = Timeline(entries: [poeEtry], policy: .after(updateDate!))
completion(timeLine)
}
}
}
}
PoetryRquest是我们的网络请求,上一篇我们使用PoetryRquest.request请求了我们的网络数据并通过Poetry来保存数据放到PoetryEntry里面 然后放到TimeLine里面 ,更新数据.那现在是基于这个思路.我们为我们的 PoetryEntry 增加一个字段imgData 字段
- 如下
//:保存数据
struct PoetryEntry: TimelineEntry {
//:这个是entry的时间节点 必须带着
let date: Date
let poetry:Poetry
var imgData:Data
}
然后通过PoetryRquest.fetchRemoteImage 来请求图片资源
static func fetchRemoteImage(urlString: String,completion: @escaping(Result<Data,Error>) -> Void) {
guard let url = URL(string: urlString) else { return }
URLSession.shared.dataTask(with: url){ (data, response, error) in
guard error == nil else{
completion(.failure(error!))
return
}
completion(.success(data!))
}.resume()
}
然后我们就看到了,timeline里面连着两个 网络请求.第一个是正常数据,第二个就是我们的图片data,我们要等我们的图片数据下载完成之后,放到PoetryEntry 然后在使用TimeLine 来刷新视图.
文章链接:https://juejin.cn/post/6904622806039232520