详解iOS14 Widget 开发相关及易报错地方处理

 更新时间:2020年10月12日 14:33:45   作者:奴良  
这篇文章主要介绍了详解iOS14 Widget 开发相关及易报错地方处理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

首先了解下如何创建

Xcode -> File -> New -> Target 找到 Widget Extension


如果你的 Widget 支持用户配置属性,则需要勾选这个(例如天气组件,用户可以选择城市),不支持的话则不用勾选

了解下创建Widget后,系统给我们生成的文件内容

下面这个代码是没有勾选 Include Configuration Intent 的地方

Provider

// Provider,顾名思义为小组件提供信息得一个struct
struct Provider: TimelineProvider {
  public typealias Entry = SimpleEntry
  
  // 编辑屏幕时,左上角选择添加小组件时候,第一次展示小组件会走这个方法
  public func snapshot(with context: Context, completion: @escaping (SimpleEntry) -> ()) {
    
  }

  // 这个方法内可以进行网络请求,拿到的数据保存在对应的 entry 中,调用 completion 之后会到刷新小组件
  public func timeline(with context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
    // 例如这是一个网络请求
    Network.request { data in
      let entry = SimpleEntry(date: renderDate, data: data)
      let timeline = Timeline(entries: [entry], policy: .after(nextRequestDate))
      completion(timeline)
    }
  }
}

Entry

官方解释: A type that specifies the date to display a widget, and, optionally, indicates the current relevance of the widget's content.

// 我的理解是就是存储小组件的数据的一个东西
struct SimpleEntry: TimelineEntry {
  let date: Date
  let data: Data
}

PlacehodlerView

// 这个是一个默认视图,例如网络请求失败、发生未知错误、第一次展示小组件都会展示这个view
struct PlaceholderView : View {
  
}

WidgetEntryView

// 这个是我们需要布局小组件长什么样子的view
struct StaticWidgetEntryView : View {
  
}

主入口

@main
struct StaticWidget: Widget {
  private let kind: String = "StaticWidget"

  public var body: some WidgetConfiguration {
    StaticConfiguration(kind: kind, provider: Provider(), placeholder: PlaceholderView()) { entry in
      StaticWidgetEntryView(entry: entry)
    }
    .configurationDisplayName("My Widget")
    .description("This is an example widget.")
  }
}

支持多Widget样式

@main
struct MainWidgets: WidgetBundle {

  @WidgetBundleBuilder
  var body: some Widget {
    Widget1()
    Widget2()
  }

}

勾选 Include Configuration Intent 之后可能出错的地方

如果你的app中设置了 Class Prefix 这下面这个 ConfigurationIntent.self 则需要加上对应的前缀

例如前缀是 XY 则需要修改为 XYConfigurationIntent.self

@main
struct MainWidget: Widget {
  private let kind: String = "MainWidget"

  public var body: some WidgetConfiguration {
    IntentConfiguration(kind: kind, intent: XYConfigurationIntent.self, provider: Provider(), placeholder: PlaceholderView()) { entry in
      IntentWidgetEntryView(entry: entry)
    }
    .configurationDisplayName("My Widget")
    .description("This is an example widget.")
  }
}

处理Widget点击事件

Widget 支持三种显示方式,分别是 systemSmall 、 systemMedium 、 systemLarge
small 样式只能用 widgetUrl 处理

@ViewBuilder
var body: some View {
  ZStack {
    AvatarView(entry.character)
      .widgetURL(url)
      .foregroundColor(.white)
  }
  .background(Color.gameBackground)
}

medium 和 large 可以用 Link 或者 widgetUrl 处理,我们看到里面有四个相同的view,即左边图片,右边文字的,这个view代码如下(Link方式)

struct RecipeView: View {
  let recipe: RecipeModel
  
  var body: some View {
    Link(destination: URL(string: "你的网址")!) {
      HStack {
        WebImageView(imageUrl: recipe.squareImageUrl)
          .frame(width: 65, height: 65)
        
        Text(recipe.adjName + recipe.name)
          .font(.footnote)
          .bold()
          .foregroundColor(.black)
          .lineLimit(3)
      }
    }
  } 
}

添加 Link 或 widgetUrl 后,点击每个 RecipeView 都会触发事件,这时候你需要在主项目中的 AppDelegate 中的如下方法进行处理

func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    
}

关于Widget中加载网络图片的时机

当我们在func timeline(withcompletion)这个方法中请求到数据拿到图片链接后,必须同步把图片解析出来,否则直接让对应的WidgetView去load url 是加载不出来的

正确的写法

Struct Model {
 ...
 let image: UIImage
}

func timeline(with context: Context, completion: @escaping (Timeline<LFPlanEntry>) -> ()) {
  Network.request { data in
    // 解析图片
    var image: UIImage? = nil
    if let imageData = try? Data(contentsOf: url) {
      image = UIImage(data: imageData)
    }
    let model = Model(image: image ?? defalutImage) // 这里给个默认图片
    let entry = SimpleEntry(date: entryDate, data: model)
    let timeline = Timeline(entries: [entry], policy: .atEnd)
    completion(timeline)
  }
}

Struct WidgetView: View {
  
  let model: Model

  @ViewBuilder
  var body: some View {
    Image(uiImage: model.image)
          .resizable()
  }

}

错误的写法(直接丢url给view去加载)

struct WidgetView : View {
  
  let model: Model

  @State private var remoteImage : UIImage? = nil
  
  let defaultImage = UIImage(named: "default")!
  
  var body: some View {
    Image(uiImage: self.remoteImage ?? defaultImage)
      .onAppear(perform: fetchRemoteImage)
  }
  
  func fetchRemoteImage() {
    guard let url = URL(string: model.url) else { return }
    URLSession.shared.dataTask(with: url){ (data, response, error) in
      if let image = UIImage(data: data!){
        self.remoteImage = image
      } else {
        print(error ?? "")
      }
    }.resume()
  }
}

基于我们的app做出来的简单效果图

Widget相关资料

Widgets

Creating a Widget Extension

Keeping a Widget Up To Date

Making a Configurable Widget

到此这篇关于详解iOS14 Widget 开发相关及易报错地方处理的文章就介绍到这了,更多相关iOS14 Widget开发内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • IOS 播放系统提示音使用总结(AudioToolbox)

    IOS 播放系统提示音使用总结(AudioToolbox)

    这篇文章主要介绍了IOS 播放系统提示音使用总结(AudioToolbox)的相关资料,需要的朋友可以参考下
    2017-05-05
  • 阿里数据iOS端启动速度优化心得

    阿里数据iOS端启动速度优化心得

    本篇文章给大家详细分析了阿里数据iOS端启动速度优化的知识点以及心得,对此有兴趣的朋友参考学习下吧。
    2018-02-02
  • iOS屏幕根据键盘自动变化高度

    iOS屏幕根据键盘自动变化高度

    这篇文章主要为大家详细介绍了iOS屏幕根据键盘自动变化高度,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07
  • IOS 开发中画扇形图实例详解

    IOS 开发中画扇形图实例详解

    这篇文章主要介绍了IOS 开发中画扇形图实例详解的相关资料,需要的朋友可以参考下
    2017-04-04
  • iOS webview捕获H5按钮方法示例代码

    iOS webview捕获H5按钮方法示例代码

    这篇文章主要给大家介绍了关于iOS webview捕获H5按钮方法的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-01-01
  • iOS使用WebView生成长截图的第3种解决方案

    iOS使用WebView生成长截图的第3种解决方案

    这篇文章主要给大家介绍了关于iOS使用WebView生成长截图的第3种解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-09-09
  • iOS点击推送消息跳到应用指定页面方法

    iOS点击推送消息跳到应用指定页面方法

    现在的推送用的越来越频繁,几乎每个应用都开始用到了。这篇文章主要介绍了iOS点击推送消息跳到应用指定页面方法,有需要的可以了解一下。
    2016-11-11
  • iOS 边下边播的实现代码

    iOS 边下边播的实现代码

    在之前项目中使用的是AVPlayer直接播放URL地址,但是不知道是相机的wifi不够稳定还是代码的问题,app总是出现缓冲卡顿。后来考虑改成边下边播模式,下面小编给大家带来了iOS 边下边播的实现代码,需要的朋友参考下吧
    2017-11-11
  • ios中图像进行压缩方法汇总

    ios中图像进行压缩方法汇总

    在Iphone上有两种读取图片数据的简单方法: UIImageJPEGRepresentation和UIImagePNGRepresentation. UIImageJPEGRepresentation函数需要两个参数:图片的引用和压缩系数.而UIImagePNGRepresentation只需要图片引用作为参数.
    2015-05-05
  • iOS动画特效之立方体翻转

    iOS动画特效之立方体翻转

    今天起为大家带来iOS动画特效合集之立方体翻转,APP如美女,动画如衣裳,赶紧为她披上漂亮的衣装吧!
    2016-08-08

最新评论