上一篇文章【iOS14】仿网易云桌面小组件(一)介绍了如果创建小组件,并使用SwiftUI
简单实现了网易云小组件的界面,本篇将从网络请求,图片同步,动态数据展示等方面来对小组件进行优化。
通过本篇文章你将学到以下几点
1、SwiftUI中的网络请求,图片同步下载
2、动态刷新小组件
3、小组件中参数传递,绑定数据,实现如下效果
SwiftUI中的网络请求,图片同步下载
首先我们根据内容先来定义数据模型
struct GKWYData {
let title: String // 标题
let desc: String // 描述
let icon: String // 图标名称
let bg: String // 背景图片名称
var bgImage: UIImage? = UIImage(named: "background") // 背景图片对象
}
// 创建默认数据
let defaultData = GKWYData(title: "每日音乐推荐", desc: "为你带来每日惊喜", icon: "cm4_disc_type_list", bg: "leida_bg")
我们创建一个类GKWYDataLoader,然后定义静态方法获取每日音乐推荐,代码如下:
struct GKWYDataLoader {
/// 请求推荐内容
/// - Parameter completion: 请求完成回调
static func request(completion: @escaping (GKWYData) -> Void) {
// 热门音乐列表接口,成功后用随机设置一个音乐为推荐音乐
// 如果获取不到则使用默认数据,保证不能为空
let url = URL(string: "https://musicapi.qianqian.com/v1/restserver/ting?format=json&from=ios&channel=appstore&method=baidu.ting.billboard.billList&type=1&size=20&offset=0")!
let request = URLRequest(url: url)
URLSession.shared.dataTask(with: request) { (data, response, error) in
if data != nil && error == nil {
let json = try! JSONSerialization.jsonObject(with: data!, options: []) as! [String: Any]
let error_code = json["error_code"] as! Int
if error_code == 22000 {
if let list = (json["song_list"] as? [[String: Any]]) {
// 获取随机数
let random = arc4random() % UInt32(list.count)
let item = list[Int(random)]
let title = item["title"] as! String
let author = item["author"] as! String
let album = item["album_title"] as! String
let desc = author + "-" + album
let cover = item["pic_radio"] as! String
var image: UIImage? = UIImage(named: "background")
// 同步网络图片到本地
if let data = try? Data(contentsOf: URL(string: cover)!) {
image = UIImage(data: data)
}
let wyData = GKWYData(title: title, desc: desc, icon: "cm4_disc_type_list", bg: "", bgImage: image)
completion(wyData)
}else {
completion(defaultData)
}
}else {
completion(defaultData)
}
}else {
completion(defaultData)
}
}.resume()
}
}
2、动态刷新小组件
给SimpleEntry增加数据模型
struct SimpleEntry: TimelineEntry {
let date: Date
let data: GKWYData
}
修改Provider里面的getTimeline方法如下,每隔5分钟刷新一次数据
func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
let currentDate = Date()
let updateDate = Calendar.current.date(byAdding: .minute, value: 5, to: currentDate)
GKWYDataLoader.request { (data) in
let entry = SimpleEntry(date: currentDate, data: data)
let timeline = Timeline(entries: [entry], policy: .after(updateDate!))
completion(timeline)
}
}
3、小组件中参数传递,绑定数据
在GKWYWidgetView中增加数据模型,并绑定数据
struct GKWYWidgetView: View {
let data: GKWYData
var body: some View {
GeometryReader { geo in
ZStack(alignment: .bottomLeading) {
// 添加背景图
Image(uiImage: data.bgImage!)
.resizable()
// 添加阴影
LinearGradient(gradient: Gradient(colors: [Color.black.opacity(0.15), Color.black.opacity(0.35)]), startPoint: .top, endPoint: .bottom)
// 添加logo
Image("cm2_clock_logo")
.resizable()
.scaledToFill()
.frame(width: 20, height: 20)
.position(x: geo.size.width - (20/2) - 10, y: (20/2) + 10)
.ignoresSafeArea(.all)
// 添加左下角的图标及文字
VStack(alignment: .leading, spacing: 5) {
HStack() {
Image(data.icon)
.resizable()
.frame(width: 20, height: 20)
Text(data.title)
.font(.system(size: 16))
.foregroundColor(.white)
}
Text(data.desc)
.font(.system(size: 14))
.foregroundColor(.white)
}.padding()
}
}
}
}
修改GKWYWidgetEntryView并传递数据
struct GKWYWidget2EntryView : View {
var entry: Provider.Entry
var body: some View {
GKWYWidgetView(data: entry.data)
}
}
然后运行小组件,就可以看到下面的效果
至此,小组件中动态显示网络数据就已经完成。
最后
本篇文章我们学到了从网络请求数据并在小组件中动态显示,接下来将会介绍给小组件增加可编辑功能
---敬请期待