自定义多个widget
@main
struct WeatherInterWidget: WidgetBundle {
@WidgetBundleBuilder
var body: some Widget {
ClassicStyle()
}
}
ClassicStyle需要在widget的Target中
配置点说明
1. PreviewProvider
用于在模拟器上直接预览,默认只预览smll类型,添加systemMedium和systemLarge可以预览另两种
2. Widget
configurationDisplayName:添加时的标题
description:添加时的描述信息
supportedFamilies:支持的尺寸
3. View,与主应用交互
- widgetURL
- Link
在主项目的SceneDelegatez代理方法中接收回调
- (void)scene:(UIScene *)scene openURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts {
/// 根据不同的URL回调做出响应
NSLog(@"%@",URLContexts);
}
4. IntentTimelineProvider
placeholder: 提供占位的方法,作为一种没有特定属性的通用可视化视图
getSnapshot:提供表示当前时间和状态的视图,可以理解为虚假或者供用户临时选择组件的展示信息。可用展示在Add Widget页面数据
getTimeline:提供视图更新数组,或者说跟上面方法形成对比的真实信息数,通过时间线来显示
功能知识点
1. 网络请求
let url = URL(string: "https://api.seniverse.com/v3/weather/now.json?key=xxxxxx&location=beijing&language=zh-Hans&unit=c")!
let request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 60.0)
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
guard error == nil else {
completion(.failure(error!))
return
}
let nowEntry = getNowDataInfo(fromData: data!,time: str);
completion(.success(nowEntry))
}
task.resume()
let url = URL(string: "https://api.seniverse.com/v3/weather/daily.json?key=xxxxxx&location=beijing&language=zh-Hans&unit=c&start=0&days=5")!
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
guard error == nil else {
completion(.failure(error!))
return
}
let testData = getThreeDayDataInfo(fromData: data!,time: str, nowEntry:nowEntry);
completion(.success(testData))
}
task.resume()
2. 解析JSON字符串
使用JSONSerialization.jsonObject解析JSON数据
- 把Foundation.Data解析为JSON格式
let json = try! JSONSerialization.jsonObject(with: data, options: []) as! [String: Any] - 解析数组
let content = json["results"] as! [Any] - 解析字典
let results:[String:AnyObject]? = content[0] as? [String:AnyObject]
3. 主app和widget之间数据通信
分别在主app和widget的Signing & Capabilties中添加App Groups,保持groupid相同
存储:
let sharedDefaults = UserDefaults(suiteName: "group.com.apuray.weatherwidget.Weather.WidgetWeather")
sharedDefaults?.setValue("三亚", forKey: "city")
读取:
var currentCity = sharedDefaults?.string(forKey: "city")
4. 在主app中控制widget刷新
刷新所有的widget
WidgetCenter.shared.reloadAllTimelines()
根据widget名称对指定的widget进行刷新
WidgetCenter.shared.reloadTimelines(ofKind: "WidgetFirst")