iOS Today Widget设置

环境: xcode10.1,iOS 12

效果图:


t.gif

demo地址,欢迎star

1.创建Target

  • File -> New ->target
iOS Today Widget设置_第1张图片
创建Target
  • 创建完成之后的效果


    iOS Today Widget设置_第2张图片
    效果图
  • 默认使用Storyboard


    iOS Today Widget设置_第3张图片
    图片.png

2.Info.plist设置

如果想代码绘制UI,要进行以下操作

  • Bundle display name:Widget在通知栏显示的名称
  • NSExtension
    如果你是使用纯代码进行开发,请按照下面进行操作:
对于 OC

1)请删除NSExtensionMainStoryboard 的键值对和MainInterface.storyboard文件;
2)请添加NSExtensionPrincipalClass这个key,并将value设置为控制器(如TodayViewController)

对于 Swift

1)请删除NSExtensionMainStoryboard 的键值对和MainInterface.storyboard文件;
2)请添加NSExtensionPrincipalClass这个key,并将value设置为控制器(如$(PRODUCT_NAME).TodayViewController)

Swift有命名空间的问题,如果不加会报如下报错

图片.png

2.Widget细节处理

iOS 8
    1. iOS8下没有折叠和展开功能,默认的Widget高度为self.preferredContentSize设置的高度。
preferredContentSize = CGSize(width: UIScreen.main.bounds.size.width, height: 110)
  • 2.iOS8下所有组件默认右移30单位,可以通过下面的方法修改上下左右的距离
func widgetMarginInsets(forProposedMarginInsets defaultMarginInsets: UIEdgeInsets) -> UIEdgeInsets {
    return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
 }
iOS 10

iOS 10以后,有两种显示模式

NCWidgetDisplayModeCompact, // Fixed height,高度固定,最低高度为110
NCWidgetDisplayModeExpanded, // Variable height,高度可变
NCWidgetDisplayModeExpanded下高度一览表

模拟器测试结果(实际结果应以真机为准).png

. 修正:iPhoneX 和XS尺寸相同,但是最大的widget高度是不同的,上图上是模拟器的测试结果,XS的的最大高度应该是748。另外widget的最小高度也不一定是110(大部分情况下是),XS的高度是98,所以最好使用系统的方法动态的获取高度(extensionContext?.widgetMaximumSize(for: .compact).height)

  • 在设置最大高度的时候要考虑到具体机型和系统
  • Widget 的收起、展开 则是通过这个代理方法:
/**
- (void)widgetActiveDisplayModeDidChange:(NCWidgetDisplayMode)activeDisplayMode withMaximumSize:(CGSize)maxSize {
    if(activeDisplayMode == NCWidgetDisplayModeCompact) {
        // 尺寸只设置高度即可,因为宽度是固定的,设置了也不会有效果
        self.preferredContentSize = CGSizeMake(0, 110);
    } else {
        self.preferredContentSize = CGSizeMake(0, 310);
    }
}
  • 在设置 UI 的过程中,若想使用本体 Target 中的类:


    iOS Today Widget设置_第4张图片
    图片.png

3.数据共享

  • 主App target设置Group
iOS Today Widget设置_第5张图片
开启Group

iOS Today Widget设置_第6张图片
添加Group标识
  • Widget target设置Group

    同上

  • Userdefault共享数据

设置数据

//主项目设置widget数据(通过Userdefaults)  AppDelegate.swift
    private func setWidgetData() {
        let userDafault = UserDefaults(suiteName: "group.tsc")
        userDafault?.set("主App名字(Userdefaults)", forKey: "FirstDataName")
        userDafault?.set("主App内容(Userdefaults)", forKey: "FirstDataContent")
        userDafault?.synchronize()
    }

取数据

//获取主项目设置widget数据(通过Userdefaults)TodayViewController.swift
    func fetchWidgetData() -> WidgetModel {
        let userDefault = UserDefaults(suiteName: "group.tsc")

        let model = WidgetModel(name: userDefault?.string(forKey: "FirstDataName") ?? "未获从主App取到名字", date: "Yesterday", content: userDefault?.string(forKey: "FirstDataContent") ?? "未从主App获取到内容", imageName: "Report_Success_icon_120x120_")
        return model
    }
  • FileManager共享数据

设置数据

    private var models: [WidgetModel] = {
        let imageNameArray = ["Report_Success_icon_120x120_", "Report_Success_icon_120x120_", "Report_Success_icon_120x120_", "Report_Success_icon_120x120_", "Report_Success_icon_120x120_"]
        let nameArray = ["Alex & Jessica(FileManager)", "Jessica(FileManager)", "Rocky(FileManager)", "Work Order(FileManager)", "Work Order(FileManager)"]
        let dateArray = ["5:30 pm", "Yesterday", "11/02/2018", "11/02/2018", "11/02/2018"]
        let conentArray = ["Rocky: Where are you Jessic?", "Rocky: Where are you Jessic?I will arrive station about 30n munites later", "Rocky: Where are you Jessic?I will arrive station about 30n munites later", "Rocky: Where are you Jessic?I will arrive station about 30n munites laterRocky: Where are you Jessic?I will arrive station about 30n munites later", "Rocky: Where are you Jessic?I will arrive station about 30n munites laterRocky: Where are you Jessic?I will arrive station about 30n munites later"]
        var array = [WidgetModel]()
        for i in 0..

取数据

 //获取主项目设置widget数据(通过FileManager)
    func setWidgetFileData() {
        let manager = FileManager.default
        var url = manager.containerURL(forSecurityApplicationGroupIdentifier: "group.tsc")
        //路径上多了个file:// 要去掉
        var urlString = url!.absoluteString.replacingOccurrences(of: "file://", with: "")
        url?.appendPathComponent("Library/MainWidget/group.json")

        urlString.append("Library/MainWidget/group.json")
        //获取json数据
        if manager.fileExists(atPath: urlString) {
            do {
                let json = try! String(contentsOf: url!)
                let modelArray = try? JSONDecoder().decode([WidgetModel].self, from: json.data(using: .utf8)!)
                models = modelArray ?? []
            }
        } else {
            print("不存在")
        }
    }

4.Scheme配置

  • 宿主App配置Scheme
iOS Today Widget设置_第7张图片
图片.png
  • Widget配置跳转
@objc func buttonDidClick(_ sender: UIButton) {
        var action = ""
        switch sender.tag {
        case 100:
            action = "scan"
        case 101:
            action = "pay"
        case 102:
            action = "rec"
        case 103:
            action = "zhuanzhang"
        case 104:
            action = "code"
        default:
            break
        }
        extensionContext?.open(URL(string: "MainWidgetScheme://action=\(action)")!, completionHandler: { (_) in
        })
    }
  • 宿主App处理跳转
 func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        let urlString = url.absoluteString
        let startIndex = urlString.startIndex
        let string = "MainWidgetScheme://action="

        if urlString.contains(string) {
            let newStartIndex = urlString.index(startIndex, offsetBy: string.count)
            let code = urlString[newStartIndex..

demo地址,欢迎star

  • 共用三方库 或者共用Framework可参考这个文章
    Widget和主App共用Framework时出现的pod问题

Extension 证书配置

你可能感兴趣的:(iOS Today Widget设置)