近期在做Widget小组件相关的开发,于是整理和记录在iOS14 Widget小组件开发过程中用到的知识点,本文将持续更新…
1、与APP数据同步
首先你得有个AppGroup,添加AppGroup,选择Target,点击Signing & Capability,再点击+Capability,找到AppGroup并双击。然后在AppGroups列表找到要使用ID,如果没有的话可以通过+新增即可。

NSUserDefault方式:
//OC NSUserDefault *store = [[NSUserDefaults alloc] initWithSuiteName:@"group.yourgroupid"]; [store setObject:@"yourvalue" forKey:@"yourkey"]; [store synchronize]; //Swift let store = UserDefaults(suiteName: "group.yourgroupid") store.setValue(@"yourvalue", forKey: @"yourkey") store.synchronize() let store = UserDefaults(suiteName: "group.yourgroupid") let obj = store.value(forKey: "yourkey") if obj == nil { } else { }
NSFileManager文件方式:
NSURL *yourFileURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"group.yourgroupid"]; yourFileURL = [yourFileURL URLByAppendingPathComponent:@"your_file_name"]; //TODO: 拿到file url后就可以做你想做的事了
2、强制刷新Widget
当需要触发刷新Widget时,可通过WidgetCenter.shared.reloadAllTimelines()刷新全部,或者通过kind string刷新某一个WidgetCenter.shared.reloadTimelines(ofKind: “your_kind_string”)
WidgetKit只存在于Swift中,所以使用Objective-C的需要引入Swift混编,通过OC调用Swift来刷新Widget,至于OC和Swift混编的相关知识请各位自行查找。
import Foundation import WidgetKit public class MyWidget: NSObject { @objc public func reloadWidget() { if #available(iOS 14.0, *) { WidgetCenter.shared.reloadAllTimelines() } else { // Fallback on earlier versions }; } }
3、显示一张图片
针对不同尺寸的Widget进行处理,通过添加Image控件进行显示。
struct PPPasswordWidgetEntryView : View { var entry: Provider.Entry //针对不同尺寸的 Widget 设置不同的 View @Environment(\.widgetFamily) var family // 尺寸环境变量 var body: some View { switch family { case.systemSmall: Image.init("AppBgImage") .resizable() .frame(minWidth: 141, maxWidth: 200, minHeight: 141, maxHeight: 200, alignment: .center) .scaledToFit() .edgesIgnoringSafeArea(.all) case.systemMedium: Image.init("AppBgImage") .resizable() .frame(minWidth: 141, maxWidth: 200, minHeight: 141, maxHeight: 200, alignment: .center) .scaledToFit() .edgesIgnoringSafeArea(.all) default: Image.init("AppBgImage") .resizable() .frame(minWidth: 141, maxWidth: 400, minHeight: 141, maxHeight: 400, alignment: .center) .scaledToFit() .edgesIgnoringSafeArea(.all) } } }
4、显示图片+文字
通过设置VStack的background来实现背景图片,通过在VStack中添加Text实现文本显示。
struct GYWidgetEntryView : View { var entry: Provider.Entry var body: some View { let themeBgName = entry.themeBgName//主题背景图片 let textColor = entry.textColor//要显示文字内容 GeometryReader{ geo in VStack { Text(entry.content) .font(.system(size: 24)) .padding(12) .minimumScaleFactor(0.2) .foregroundColor(textColor) }.frame(width: geo.size.width, height: geo.size.height) .background(Image(themeBgName) .resizable() .scaledToFill()) .padding(0) } } }
5、文字自适应
Text(entry.content) .font(.system(size: 24)) .padding(12) .minimumScaleFactor(0.2) .foregroundColor(textColor)
5、日期转字符串
//日期 -> 字符串 func date2String(date:Date, dateFormat:String = "yyyy-MM-dd HH:mm:ss") -> String { let formatter = DateFormatter() formatter.locale = Locale.init(identifier: "zh_CN") formatter.dateFormat = dateFormat let date = formatter.string(from: date) return date }
6、增加多组Widget
删除原Widget的@main声明,增加WidgetBundle
@main struct Widgets: WidgetBundle { @WidgetBundleBuilder var body: some Widget { BJXX2Widget(); BJXXWidget() } }
7、设置只显示小组件,中号和大号组件不显示
通过supportedFamilies方法进行设置,参数为支持的WidgetFamily数组,共包含了.systemSmall、.systemMedium、.systemLarge。
struct BJXX2Widget: Widget { let kind: String = "BJXX2Widget"//北京限行日历小组件 var body: some WidgetConfiguration { StaticConfiguration(kind: kind, provider: Provider()) { entry in BJXX2WidgetEntryView(entry: entry) } .configurationDisplayName("一周限行") .supportedFamilies([.systemSmall]) .description("限行号码一目了然") } }
8、自定义View
如何实现尾号限行日历小组件中一天的布局呢?自定义DayItemView,通过VStack包裹日期和限行尾号即可。

struct DayItemView : View { let day: String let number: String init(day: String, number:String) { self.day = day self.number = number } var body: some View { VStack { Spacer() Text(day)//那一天,例如:16 .font(.system(size: 12)) Text(number)//限行尾号,例如2和7 .font(.system(size: 9)).foregroundColor(.gray) Spacer() } .frame(width: 32, height: 32, alignment: .center) } }
8、审核相关
小组件内容应该丰富的个性化的动态的,避免提供静态内容。要不很容易就审核人员4.4拒绝了。
如果你的小组件不包含Siri快捷键指令,请在提交审核时在备注中写上:不包含Siri快捷指令。如不不填写的话可能会被打回补充信息,询问是否包含Siri快捷键指令或如何操作等等,之前我增加Widget后首次提交审核审就是被这样打回的。
未完待续…