需求:
我们需要在app应用内刷新时间线,让桌面小组件加载最新的内容。即app内修改了共享数据后,需要通知桌面小组件强制刷新,显示改变后的内容。
当某种情况影响到小组件的当前时间线时,您的 App 可以指示 WidgetKit 请求一个新的时间线。在上面的游戏小组件示例中,如果 App 收到一条推送通知,说明队友已为角色提供了治疗药水,则 App 可以指示 WidgetKit 重新载入时间线并更新小组件的内容。为重新载入特定类型的小组件,您的 App 会使用
WidgetCenter.shared.reloadTimelines(ofKind: "你小组件的kind")
看完此篇文章您将实现一下效果:
项目配置和实现:
注意点:共享数据组请用自己的开发者账号进行调试
app内代码:
#import "ViewController.h"
#import "MyJbbDemo-Swift.h"
@interface ViewController ()
@property (nonatomic, strong) UIButton *startButton;
@property (nonatomic, assign) bool isChange;
@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.self.view.backgroundColor = [UIColor whiteColor];UIButton *startButton = [UIButton buttonWithType:UIButtonTypeSystem];startButton.frame = CGRectMake(0, 0, 200, 50);startButton.backgroundColor = UIColor.greenColor;startButton.layer.cornerRadius = 25;[self.view addSubview:startButton];[startButton setTitle:@"切换小组件上显示的图片" forState:UIControlStateNormal];[startButton setTintColor:[UIColor whiteColor]];startButton.center = self.view.center;[startButton addTarget:self action:@selector(startClick:) forControlEvents:UIControlEventTouchUpInside];NSFileManager *fileManager = [NSFileManager defaultManager];NSURL *pathURL = [fileManager containerURLForSecurityApplicationGroupIdentifier:@"你的组ID"];pathURL = [pathURL URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.png", @"testWidgetImage"]];UIImage *image = [UIImage imageNamed:@"1111"];BOOL success = [UIImagePNGRepresentation(image) writeToURL:pathURL atomically:YES];}- (void)startClick:(UIButton *)sender {NSFileManager *fileManager = [NSFileManager defaultManager];NSURL *pathURL = [fileManager containerURLForSecurityApplicationGroupIdentifier:@"你的组ID"];pathURL = [pathURL URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.png", @"testWidgetImage"]];UIImage *image = [UIImage imageNamed:@"2222"];if(self.isChange){image = [UIImage imageNamed:@"1111"];}self.isChange = !self.isChange;BOOL success = [UIImagePNGRepresentation(image) writeToURL:pathURL atomically:YES];dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{WidgetTool *tool = [[WidgetTool alloc] init];[tool refreshAllWidget];[[UIApplication sharedApplication] performSelector:@selector(suspend)];});
}@end
因为我的项目是oc项目,所以我使用了侨接,来调用swift方法去通知小组件刷新:
import WidgetKit@objcMembers class WidgetTool: NSObject {@available(iOS 14, *)@objc func refreshAllWidget() {
#if arch(arm64) || arch(i386) || arch(x86_64)WidgetCenter.shared.reloadAllTimelines()
#endif}}
小组件的代码就比较简单了:
import WidgetKit
import SwiftUI
import Intentsstruct Provider: IntentTimelineProvider {func placeholder(in context: Context) -> SimpleEntry {SimpleEntry(date: Date(), configuration: ConfigurationIntent())}func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) {let entry = SimpleEntry(date: Date(), configuration: configuration)completion(entry)}func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
// var entries: [SimpleEntry] = []
//
// // Generate a timeline consisting of five entries an hour apart, starting from the current date.
// let currentDate = Date()
// for hourOffset in 0 ..< 5 {
// let entryDate = Calendar.current.date(byAdding: .hour, value: hourOffset, to: currentDate)!
// let entry = SimpleEntry(date: entryDate, configuration: configuration)
// entries.append(entry)
// }
//
// let timeline = Timeline(entries: entries, policy: .atEnd)
// completion(timeline)var entries: [SimpleEntry] = []let currentDate = Date()for hourOffset in 0 ... 23 {let entryDate = Calendar.current.date(byAdding: .hour, value: hourOffset, to: currentDate)!let entry = SimpleEntry(date: entryDate, configuration: configuration)entries.append(entry)}let timeline = Timeline(entries: entries, policy: .never)completion(timeline)}
}struct SimpleEntry: TimelineEntry {let date: Datelet configuration: ConfigurationIntent
}struct testExtensionEntryView : View {var entry: Provider.Entryvar body: some View {getImage().resizable().frame(width: .infinity, height: .infinity).scaledToFill()
// Text("aaaaaa")
// .foregroundColor(Color.red)}
}struct testExtension: Widget {let kind: String = "testExtension"var body: some WidgetConfiguration {IntentConfiguration(kind: kind, intent: ConfigurationIntent.self, provider: Provider()) { entry intestExtensionEntryView(entry: entry)}.configurationDisplayName("My Widget").description("This is an example widget.")}
}struct testExtension_Previews: PreviewProvider {static var previews: some View {testExtensionEntryView(entry: SimpleEntry(date: Date(), configuration: ConfigurationIntent())).previewContext(WidgetPreviewContext(family: .systemSmall))}
}func getImage() -> Image {let manager = FileManager.defaultlet floderURL:URL = manager.containerURL(forSecurityApplicationGroupIdentifier: "你的组ID")!let str = "testWidgetImage.png"let fileURL:URL = floderURL.appendingPathComponent(str)do {let data: Data = try Data.init(contentsOf: fileURL)let image = UIImage.init(data: data)return Image(uiImage: image!)} catch let error{print(error.localizedDescription)return Image("WidgetBackground")}
}
demo下载案例:
https://download.csdn.net/download/IT_Scratch/87389805?spm=1001.2014.3001.5501https://download.csdn.net/download/IT_Scratch/87389805?spm=1001.2014.3001.5501