隐式意图调用
If you are coming from my previous article, Welcome back! If you are just starting with the widgets, I would recommend you to go through my previous article first. In this article we are going to modify our already created fake AdvancedWidget from the previous article and make it actually an advanced one! ;)
如果您来自我的上一篇文章,欢迎回来! 如果您只是从小部件入手,建议您阅读上一篇文章 第一。 在本文中,我们将修改上一篇文章中已经创建的虚假AdvancedWidget ,并使其实际上成为高级文章! ;)
In previous article we just displayed static data on our widget. But in real life you might need to fetch data from an api. Making network calls for widgets are as easy as you would expect. If you already have a web service you can simply expose it to your widget extension by selecting your widget target in Target Membership.
在上一篇文章中,我们只是在小部件上显示了静态数据。 但是在现实生活中,您可能需要从api获取数据。 对小部件进行网络调用就像您期望的那样容易。 如果您已经拥有Web服务,则只需在Target Membership中选择您的窗口小部件目标即可将其公开给您的窗口小部件扩展。
If you don’t have one, go ahead and create one for your extension. Don’t forget to select the your widget extension under Targets.
如果您没有,请继续为扩展名创建一个。 不要忘记在“ 目标”下选择您的窗口小部件扩展名。
Create a model depicting your actual api request response. For the demo purpose I am making a simple model User with two properties Name and Profession.
创建一个描述您的实际api请求响应的模型。 出于演示目的,我将创建一个具有两个属性Name和Profession的简单模型User 。
Also we are going to mock api response instead of making actual api request. So I am creating demo response. Note that you shouldn’t use try!, catch your errors properly using do-catch.
另外,我们将模拟api响应,而不是发出实际的api请求。 因此,我正在创建演示响应。 请注意,您不应该使用try! ,请使用do-catch正确捕获错误。
In your WebService class write the method that communicates with the network. You can replace the commented code with your actual api request in the following code:
在您的WebService类中,编写与网络通信的方法。 您可以在以下代码中用实际的api请求替换注释的代码:
So, we are done with the our basic network set up. Now, coming back to our AdvancedProvider,. getTimeline is the method that provides entries to your widget that will be displayed on your widget view, feeling Deja Vu?? Go ahead and call your fetchUserData method you just created. Create an entry with your user data received from the method and pass it to the completion handler. Also, you should handle your errors gracefully. I am going to show static data in case my api call fails. Caching is also a way to go, You decide! Your getTimeline: method looks like this now:
至此,我们完成了基本网络的设置。 现在,回到我们的AdvancedProvider 。 getTimeline是一种为窗口小部件提供条目的方法,该条目将显示在窗口小部件视图上,感觉像Deja Vu? 继续并调用刚刚创建的fetchUserData方法。 使用从方法接收到的用户数据创建一个条目,并将其传递给完成处理程序。 另外,您应该优雅地处理错误。 如果我的api调用失败,我将显示静态数据。 缓存也是一种方法,您决定! 您的getTimeline:方法现在看起来像这样:
Now run your application, you would be able to see the new text! Voila!!
现在运行您的应用程序,您将能够看到新文本! 瞧!
In previous article we worked with Static Intent configuration. Let’s create a dynamic intent. Choose File > New > File > SiriKit Intent Definition File.
在上一篇文章中,我们使用了静态意图配置。 让我们创建一个动态意图。 选择“ 文件”>“新建”>“文件”> SiriKit Intent Definition File。
Click next, provide name UserCategories. Check both the Targets.
单击下一步,提供名称UserCategories。 检查两个目标。
Open your UserCategories definition file. Click on + at the bottom, create New Intent and provide name UserCategories.
打开您的UserCategories定义文件。 单击底部的+ ,创建新意图并提供 名称UserCategories 。
For this Intent we need to fill out few fields here. Select Category as View. Provide meaningful Description. Select checkbox Intent is available for widgets.
为此,我们需要在此处填写一些字段。 选择类别作为视图。 提供有意义的描述。 选择复选框意向可用于窗口小部件。
Now we will create an Enum to supply data to our intent. Click on + icon, create New Enum. Provide name Users. You can change Display Name as you like. Add the cases you want.
现在,我们将创建一个枚举以将数据提供给我们的意图。 单击+图标,创建New Enum 。 提供名称Users 。 您可以根据需要更改显示名称 。 添加所需的案例。
Now select UserCategories again, under Parameters, click on + icon at the bottom, provide name users. Change type to the enum Users we just created.
现在再次选择UserCategories ,在Parameters下,单击底部的+图标,提供名称用户。 将类型更改为我们刚刚创建的枚举用户 。
Provide Summary and Description that makes sense unlike below:
提供与以下内容不同的摘要和说明 :
Now our Intent Definition is complete! Easy right?! Now million dollars question is how will our widget use this Intent Definition, hmm..??
现在我们的意图定义已经完成! 容易吧?! 现在,百万美元的问题是我们的小部件将如何使用此Intent定义,嗯?
You need to expose your intent to the application. Go to Project Targets, add your intent under Supported Intents.
您需要向应用程序公开您的意图。 转到“ 项目目标” ,在“ 受支持的意图”下添加您的意图。
Go back to your AdvancedWidget, change StaticConfiguration to IntentConfiguration, and Complier starts yelling, yet again!! It’s alright we’re gonna fix it one by one.
返回到AdvancedWidget,将StaticConfiguration更改为IntentConfiguration,然后 编译器 开始 再次大喊大叫! 没关系,我们将一一修复。
It needs extra parameter, with the help of xcode, apply FixIt. It is asking for the intent, provide UserCategoriesIntent.self here.
它需要额外的参数,借助于xcode,应用FixIt。 它正在询问意图, 请在此处提供UserCategoriesIntent.self 。
Now compiler complains that our AdvancedProvider does not conform to the IntentTimelineProvider, rightly so. Go ahead, change the conformance to IntentTimelineProvider from TimelineProvider.
现在,编译器抱怨我们的AdvancedProvider不符合IntentTimelineProvider ,这是正确的。 继续,从TimelineProvider更改对IntentTimelineProvider的一致性。
Now, IntentTimelineProvider demands few changes. First, add typealias for Intent i.e UserCategoriesIntent. Second, add configuration: UserCategoriesIntent parameter to your getSnapshot and getTimeline methods. Xcode auto-complete should help you here. Now your AdvancedProvider should look like this:
现在, IntentTimelineProvider需要进行一些更改。 首先,为Intent添加类型别名 ,即UserCategoriesIntent。 其次,将配置:UserCategoriesIntent参数添加到getSnapshot和getTimeline方法中。 Xcode自动完成功能可以为您提供帮助。 现在,您的AdvancedProvider应该如下所示:
Now run your application again, long press your widget, you should see Edit Widget option now. Select Choose from the dialog box, you will see the list of users you provided through the enum. Voila!!!
现在再次运行您的应用程序,长按您的窗口小部件,您现在应该会看到Edit Widget选项。 从对话框中选择选择 ,您将看到通过枚举提供的用户列表。 瞧!
So far so good, right!! Now I want to display whatever user selects from the options. We are going to write a simple method to map the selected indices to the strings we are going to display. Configuration parameter will be passed from the getTimeline method.
到目前为止一切都很好,对! 现在,我想显示用户从选项中选择的任何内容。 我们将编写一个简单的方法将所选索引 映射到要显示的字符串 。 配置参数将从getTimeline方法传递。
Call this method from the getTimeline method. Use returned string to display in your AdvancedEntry.
从getTimeline方法调用此方法。 使用返回的字符串显示在AdvancedEntry中 。
That’s it, we are done with the dynamic intent configuration. Go on experiment a bit.
就是这样,我们完成了动态意图配置。 继续进行实验。
Another important aspect of widgets is Deeplinking. When you tap on the widget it should take you to the specific part of your application. systemSmall widgets are one large tap area while systemMedium and systemLarge can use new SwiftUI link API to create tappable zones within the widget. So deeplinking can be done in two ways:
小部件的另一个重要方面是Deeplinking 。 当您点击小部件时,它应该带您到应用程序的特定部分。 systemSmall小部件是一个较大的点击区域,而systemMedium和systemLarge可以使用新的SwiftUI 链接API在小部件内创建可点击区域。 因此可以通过两种方式进行深层链接:
For systemSmall widgets, you can add .widgetURL modifier onto your SwiftUI view. It works the same way as your URL schemes. You can handle it in openURL: method.
对于systemSmall小部件 ,可以将.widgetURL修饰符添加到SwiftUI视图中。 它的工作方式与URL方案相同。 您可以在openURL:方法中处理它。
.widgetURL(URL(string: “WidgetsDemo://relativeText”))
.widgetURL(URL(string:“ WidgetsDemo:// relativeText”))
2. For systemMedium and systemLarge widgets, you can use new SwiftUI link API
2. 对于systemMedium和systemLarge小部件,您可以使用新的SwiftUI 链接API
Link(destination: URL(string: “WidgetsDemo://relativeText”)!)
链接(目标:URL(字符串:“ WidgetsDemo:// relativeText”)!)
That’s it!! We started with a very simple widget, made a fake advanced widget to make an actual advanced one. Quite a journey right?!? Take a break, if you want to learn bit more, proceed ahead or come back later :). You can checkout the source code here.
而已!! 我们从一个非常简单的小部件开始,制作了一个伪造的高级小部件,使之成为实际的高级小部件。 一段旅程对吗?!? 稍事休息,如果您想学习更多,请继续前进或稍后再返回:)。 您可以在此处签出源代码 。
In this example we provided hard coded data to our widget configuration, but we may require to get the data via api call. Because our configuration is a SiriKit Intent, we can provide a dynamic list of options with an Intent Extension. Go to File > New > Target> Intents Extension.
在此示例中,我们向小部件配置提供了硬编码数据,但我们可能需要通过api调用获取数据。 因为我们的配置是SiriKit Intent ,所以我们可以通过Intent Extension提供动态的选项列表。 转到文件>新建>目标>意向扩展。
Provide the product name WidgetsDemoIntentHandler, make sure the Starting point is None. Then Finish.
提供产品名称WidgetsDemoIntentHandler,确保起点为None 。 然后完成 。
Make sure you expose your UserCategories.intentdefinition to this extension also.
确保也将您的UserCategories.intentdefinition暴露给该扩展名。
Select WidgetsIntentHandler under Targets, enter UserCategoriesIntent in Supported Intents.
根据目标选择WidgetsIntentHandler,在支持意图进入UserCategoriesIntent。
Coming back to UserCategories.intentdefinition file, instead of using that previously created enum, we are going to create a New Type. Click on + icon at the bottom and create New Type. Name it DynamicUser.
回到UserCategories.intentdefinition文件,而不是使用先前创建的枚举,我们将创建一个New Type 。 单击底部的+图标,然后创建“ 新类型” 。 将其命名为DynamicUser。
In your UserCategories, change type to DynamicType. And make sure you select the Dynamic Options checkbox.
在您的UserCategories中,将类型更改为DynamicType 。 并确保选中“ 动态选项”复选框 。
Now, in IntentHandler.swift file, add UserCategoriesIntentHandling conformance to IntentHandler class. This protocol will provide the abstract Dynamic options methods. Type provide and xcode with help you with autocomplete. Implement provideUsersOptions method, to provide dynamic options for your widget. You can make a network call here to fetch options from an api. I am going to use static data for this demo, your IntentHandler class should look like this:
现在,在IntentHandler.swift文件中,将UserCategoriesIntentHandling一致性添加到IntentHandler类。 该协议将提供抽象的动态选项方法。 键入provide和xcode可以帮助您完成自动完成。 实现ProvideUsersOptions方法,为小部件提供动态选项。 您可以在此处进行网络调用,以从api获取选项。 我将在此演示中使用静态数据,您的IntentHandler类应如下所示:
Pretty simple, right!! Go ahead and run your code, you will see new options now:
很简单,对! 继续运行代码,现在您将看到新的选项:
That’s it, we are done with the dynamic configuration.
就是这样,我们完成了动态配置。
2. Handling Dates: In order make your widgets lively, swiftUI provides special initializer on text that takes date and style to format it for you. While using this initializer the counter will count up or down from the specified date automatically as time passes.
2. 处理日期:为了使您的窗口小部件生动活泼,swiftUI在文本上提供了特殊的初始化程序,该初始化程序需要日期和样式来为您设置格式。 使用此初始化程序时,计数器将随着时间的流逝从指定日期开始自动递增或递减计数。
3. Rounded Rectangles: Coordinate the corner radius of your content with the corner radius of the widget. If you want your view to be concentric with your widget you can use corner radius modifier but as the corner radius of widgets varies on different devices and platforms, you have to handle multiple cases for that. Instead of all this we can use ContainerRelativeShape. ContainerRelativeShape is a new Shape type that will take on the path of the nearest container specified by the parent.
3. 圆角矩形 :将内容的角半径与小部件的角半径进行协调。 如果希望视图与窗口小部件同心,则可以使用转角半径修改器,但是由于窗口小部件的转角半径在不同的设备和平台上会有所不同,因此您必须处理多种情况。 除了所有这些,我们还可以使用ContainerRelativeShape 。 ContainerRelativeShape是一种新的Shape类型,它将采用父级指定的最近容器的路径。
Pretty simple!!
很简单!
PS: This article is written for iOS 14 beta with Xcode 12.0 beta 4, minor syntax changes are expected in future.
PS:本文是针对带有Xcode 12.0 beta 4的iOS 14 beta编写的,预计将来会有较小的语法更改。
I hope you found this article worth your time!!
希望您觉得这篇文章值得您光顾!!
Thanks,
谢谢,
Ritu
里图
翻译自: https://medium.com/@ritu734/advanced-widgets-network-calls-deeplinking-intent-configuration-30c697e09789
隐式意图调用
相关资源:微信小程序源码-合集6.rar