NotificationCenter
NotificationCenter 框架提供了实现桌面通知中心组件的接口,主要包含一个类和一个协议。
NCWidgetController
该类主要用来设置桌面中的组件是应该隐藏还是显示,例如,在点击组件跳转到主应用程序后,需要隐藏组件。
或者,在使用主应用程序添加某些事项后,需要其显示在桌面组件中。
+ (instancetype)widgetController;
- (void)setHasContent:(BOOL)flag forWidgetWithBundleIdentifier:(NSString *)bundleID;
NCWidgetController
虽然以Controller
结尾,但其父类是NSObject
。
NCWidgetProviding
该协议主要定义了两个方法,通过这两个方法,可以更新组件状态。
- (void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult result))completionHandler;
- (void)widgetActiveDisplayModeDidChange:(NCWidgetDisplayMode)activeDisplayMode withMaximumSize:(CGSize)maxSize NS_AVAILABLE_IOS(10_0);
组件默认高度是固定的 110 个点,可以通过修改 NSExtensionContext
的 NCWidgetAdditions
分类中的属性值来使组件支持折叠和展开。
@property (nonatomic, assign) NCWidgetDisplayMode widgetLargestAvailableDisplayMode NS_AVAILABLE_IOS(10_0);
@property (nonatomic, assign, readonly) NCWidgetDisplayMode widgetActiveDisplayMode NS_AVAILABLE_IOS(10_0);
修改属性 widgetLargestAvailableDisplayMode
的值可以将其设置为可以折叠和展开的,而 widgetActiveDisplayMode
属性值是只读的,实时表示当前的组件是处于折叠状态还是展开状态,他实际与上面的协议方法中的 activeDisplayMode
参数的值是一致的。
NCWidgetDisplayMode
是枚举值,其包含两个值,分别表示固定高度和可折叠。
typedef NS_ENUM(NSInteger, NCWidgetDisplayMode) {
NCWidgetDisplayModeCompact, // Fixed height
NCWidgetDisplayModeExpanded, // Variable height
} NS_ENUM_AVAILABLE_IOS(10_0);
使用
组件的创建十分简单,其作为一个应用的扩展,只能在创建一个应用之后,创建一个 target
,并选择 Today Extention
扩展。
模版会自动创建一个 TodayViewController
类,并且遵循 NCWidgetProviding
协议。
在 viewDidLoad
方法中将组件设置为可折叠的。
- (void)viewDidLoad {
[super viewDidLoad];
NSExtensionContext *context = [self extensionContext];
context.widgetLargestAvailableDisplayMode = NCWidgetDisplayModeExpanded;
}
实现 NCWidgetProviding
协议中的方法,根据不同状态来设置 preferredContentSize
的值,从而改变组件的高度。
- (void)widgetActiveDisplayModeDidChange:(NCWidgetDisplayMode)activeDisplayMode
withMaximumSize:(CGSize)maxSize {
if (activeDisplayMode == NCWidgetDisplayModeExpanded) {
self.preferredContentSize = CGSizeMake(maxSize.width, 600);
}else {
self.preferredContentSize = maxSize;
}
}
之后,为组件添加一个点击事件,使其跳转到主应用程序中,并且隐藏组件,在 10 秒后再次显示组件。
- (IBAction)btnClickedOfOpen:(UIButton *)sender {
NSExtensionContext *context = [self extensionContext];
[context openURL:[NSURL URLWithString:@"HXDemo://title=test&content=111111"]
completionHandler:^(BOOL success) {
[self showOrHideWidget:NO];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(10 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self showOrHideWidget:YES];
});
}];
}
- (void)showOrHideWidget:(BOOL)isShow {
NSString *bundleID = [[NSBundle mainBundle]objectForInfoDictionaryKey:(NSString *)kCFBundleIdentifierKey];
[[NCWidgetController widgetController]setHasContent:isShow forWidgetWithBundleIdentifier:bundleID];
}
这里实现跳转的方式,类似于不同应用间的跳转,需要先在主应用程序中添加指定的协议名称。
参考文章: