iOS8中Today Extension(Widget)的使用

作者: 进化中的程序猿 | 来源:发表于2015-10-30 18:23 被阅读4085次

扩展(Extension)是iOS 8中新引入的特性。iOS 8系统有6个支持扩展的系统区域,分别是

  • 今日插件(Today widget)
  • 分享(Share)
  • 操作(Action)
  • 图片编辑(Photo Editing)
  • 文档管理(Document Provider)
  • 自定义键盘(Custom keyboard)

支持扩展的系统区域也被称为扩展点。对于赛事比分,股票、天气、快递,位置信息等需要实时获取的信息,可以在通知中心的Today视图中创建一个Today扩展实现。Today扩展又称为Widget,本文主要是介绍Today Extension的用法。
苹果文档:https://developer.apple.com/library/ios/documentation/General/Conceptual/ExtensibilityPG/NotificationCenter.html
如图就是Widget效果(UC浏览器的)

E221C469511CDE6687B26BC7F6A49362.png
Widget的创建直接在targets里点击下边添加就可以了
3CE808F1-1E39-4892-886A-DD00386682AF.png
Xcode6新建的是自带SB的,直接在模拟器运行,注意图中箭头处 379887E7-8DF6-4C99-892D-E85138424B3A.png

运行效果,熟悉的Hello World

B8A41B2A-B787-45A7-BF35-CFA822F561C2.png

博主习惯了没有用SB,修改Info.plist文件,删除SB即可


094C49C8-5D98-49AF-BE78-043E645535E1.png

在TodayViewController的- (void)viewDidLoad方法种添加

self.preferredContentSize = CGSizeMake(0, 200);
self.view.backgroundColor = [UIColor redColor];

运行是如图效果


7EE8AABD-8624-4BBA-949F-1E99446510A9.png

值得注意:
1、尽量不要使用背景,默认的毛玻璃效果很好,也比较统一;
2、尽量保持默认的缩进,即左边会空几个像素。
如果想改变默认缩进,有一个方法:

- (UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:(UIEdgeInsets)defaultMarginInsets{
   return UIEdgeInsetsZero;
}

在TodayViewController里面实现以下,缩进就没有了,下面说几点关键的

1.共享数据

插件和主应用是独立的两个进程,以前是无法共享数据的,现在可以通过AppGroup来共享数据,同属于一个group的App可以共享数据

C2108126-AF89-412D-86F8-54F5C63369EE.png

target里选择主应用打开App Group,如果之前没有,则新加group,id格式可如图,创建之后,在你的Widget里同样地方勾选上即可,程序间共享数据使用的是

//存
NSUserDefaults *shared = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.xxxx.app"];
[shared setObject:@"value" forKey:@"key"];
[shared synchronize];

获取数据

//取
NSUserDefaults *shared = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.xxxx.app"];
[shared objectForKey:@"key"];

Name的名字跟上边添加的App Group需要一致

2.跳转到主应用

在widget里按钮添加点击事件,跳转到主app不同页面,widget里是没有UIApplication类的,所以相关方法都不能用,所以self.extensionContext代指当前widget

- (void)skip:(UIButton *)button
{
   if (button.tag == 1) {
       [self.extensionContext openURL:[NSURL URLWithString:@"iOSWidgetApp://action=GotoHomePage"] completionHandler:^(BOOL success) {
    }];
}
   else if(button.tag == 2) {
       [self.extensionContext openURL:[NSURL URLWithString:@"iOSWidgetApp://action=GotoOtherPage"] completionHandler:^(BOOL success) {
    }];
   }
}

主app里添加协议


EF825E95-5B33-4063-AF42-7E9008807147.png

然后主app里解析

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
    NSString* prefix = @"iOSWidgetApp://action=";
    if ([[url absoluteString] rangeOfString:prefix].location != NSNotFound) {
        NSString* action = [[url absoluteString] substringFromIndex:prefix.length];
        if ([action isEqualToString:@"GotoHomePage"]) {
        
        }
        else if([action isEqualToString:@"GotoOtherPage"]) {
        
        }
    }
    return  YES;
}

3.国际化问题

建议参考下这微博主http://www.jianshu.com/p/0efd62ee033a 2.6处所提到的,这点需要注意

4.网络请求

常用的AF和MK框架中都有用到UIApplication类,无法编译通过,可以自行修改相关地方,也可以直接使用AFHTTPSessionManager类,

164F9181-4802-470B-87C3-AB086896A9CF.png

相关类这些,都没有用到UIApplication(AFKit.h和AFHTTPShareRequest.h是我自己写的两个类),一个是头文件合集,一个单例类
AFKit.h
#ifndef AFKit_h
#define AFKit_h
#endif /* AFKit_h */

#ifdef __OBJC__
#import "AFHTTPSessionManager.h"
#import "AFNetworkReachabilityManager.h"
#import "AFSecurityPolicy.h"
#import "AFURLResponseSerialization.h"
#import "AFHTTPSessionManager.h"
#import "AFURLSessionManager.h"
#endif

AFHTTPShareRequest.h
#import "AFHTTPSessionManager.h"

@interface AFHTTPShareRequest : AFHTTPSessionManager

+ (instancetype)sharedClient;

@end

AFHTTPShareRequest.m
#import "AFHTTPShareRequest.h"

@implementation AFHTTPShareRequest

+ (instancetype)sharedClient
{
    static AFHTTPShareRequest *client = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        client = [[AFHTTPShareRequest alloc] init];
    });
    return client;
}
@end

(报错的话看下是不是少导入哪个类库了?)
最后再说几点细节的地方
- (void)viewDidLoad
方法并不是每次下拉都会调用(甚至很少调用),但是
- (void)viewWillAppear:(BOOL)animated
方法一定是会调用的,所以数据实时更新的代码最好不要写在 - (void)viewDidLoad方法里;第二点,断点调试时,需要用Today 来运行widget才有用,并且用真机调试有时打断点不一定有用,用模拟器一定有用,我感觉这是个bug,用模拟器调试时每次改动的代码需要把模拟器退出再重启(注意这点)才会生效,真机不需要。
暂时想到的就这么写东西。第一次开发Widget坑其实挺多的,建议下手前先多看几篇相关文章,会顺利许多,如有疑问,欢迎探讨
ps:评论有人提到划出屏幕后再划回来不能交互,我测试了下,线上版本,iphone6,6p(9.3.2)、iphone6(8.3)没有这个问题,但是开发版本确实有这个问题,不知道是不是开发版本的bug,如有知道此问题的,欢迎留言

相关文章

网友评论

  • LV大树:谢谢。好文。
  • 可惜你不是我的双子座:if判断就是控制跳转到不同页面的,在里面写一个通知中心没有用!只会跳转到主界面,其他界面没用!
  • 让我走的潇洒一点:2.跳转到主应用 这个,,,是怎么跳转到app里面不同页面的?求解
    让我走的潇洒一点:@进化中的程序猿 今日插件里面是2个按钮,上面打错了
    让我走的潇洒一点:@进化中的程序猿 是呀,我就是想知道if ([action isEqualToString:@"GotoHomePage"]) {

    }这个if里面怎么写啊,,,比如我有2个tabbar,首页,我的,,,,在今日插件里面有三个按钮,分别进入首页页面,我的页面。。。。。这个怎么写呢
    进化中的程序猿:你看下“然后主app里解析”这几个字下面那段代码,if判断就是控制跳转到不同页面的
  • o0下一站生活0o:有没有源码啊。
  • zero000:在执行过widgetPerformUpdateWithCompletionHandler:方法之后,self.view.frame.size.height发生改变了,所以导致视图显示不完全,我想问下有什么解决办法吗?
  • zero000:我添加一个App Groups之后,steps:Add the"APP Groups containers"entitilemanet to your Apple ID 下面显示:Communication with Apple field
    搞了好久没搞定,这个有什么解决的办法吗
  • 背着吉他去流浪:有一个疑问, 我是iPhone 5s, 系统是iOS 9.3.3, Today Extension在模拟器上是可以正常显示的, 一旦装到真机就不显示了, 这是啥问题? 求解~~
    背着吉他去流浪:@张囧瑞 解决了, 因为挂掉了
    张囧瑞:@背着吉他去流浪 哥们儿你这个问题解决了吗?我也遇到了同样的问题
  • 751fc49dcbfd:划出屏幕后 再回来 就不能响应交互了 遇到过吗 好奇葩。。
    进化中的程序猿:@1140752635 你打个正式包试试,我刚测试了下线上版本没有这个问题,开发的有
    751fc49dcbfd:@进化中的程序猿有消息了 回复我。 纠结中
    进化中的程序猿:@1140752635 嗯,我也刚注意到,我查查什么原因,如果你找到解决方案,欢迎留言
  • 消逝彼得:你好,我的today要显示图片,用userdefault传一个自定义类,在主应用内部还没问题,但是在today里就不行,我估计是today与主应用不能共用一个model,这个请问有解决办法么 :wink:
    消逝彼得:@进化中的程序猿 哈哈,太谢谢啦,昨天纠结我一天,今天一大早看到你的回复就解决了,祝工作顺利事业有成哈!:smile:
    进化中的程序猿:@消逝彼得 我想你的问题出在你没把主应用里的model类导入到today里,你可以先把你要在today里使用的类复制到桌面,把工程里的删了再重新添加一次,选择“add to targets”的时候注意下边勾选上你的扩展的target,应该就可以了
  • 小小麻qiao儿:怎么导入AF呀?用cocoapods管理,完全不会添加,求指导:pray:
    消逝彼得:@Huzi_鱼 导入AF? widget不是不可以联网么 :hushed:
    小小麻qiao儿:@进化中的程序猿 嗯嗯,谢谢!我直接用代码导了:grin::grin:
    进化中的程序猿:@Huzi_鱼 cocoapods我也用的不6,你可以尝试下选中要包含在扩展里的类的.m文件,右侧Target Membership里勾选上你的today,然后看下compile sources里是否添加了你需要的类,你试下吧
  • 4057ddd1acf9:网络请求的时候只用你说的那个类,为啥还报错呢
    进化中的程序猿:@简单_流年 你看下我更新了下,你的错误是?
  • ae971c1cc8c4:我导入网络库报错,你是如何网络请求的啊
    进化中的程序猿:@90_人生不一 导入错误是不是少了哪个类库? 网络请求 你看下我更新的地方
    ae971c1cc8c4:@进化中的程序猿 加个好友呗😁694921882
    进化中的程序猿:@90_人生不一 你看下你的网络库,不能用UIApplication这个类相关,最新的AFNetWorking类库的AFHTTPSessionManager类,可以直接用,不用修改什么

本文标题: iOS8中Today Extension(Widget)的使用

本文链接:https://www.haomeiwen.com/subject/mtbfhttx.html