大多数浏览器和
Developer App 均支持流媒体播放。
-
整合 SwiftUI
SwiftUI 让您可以整合您在任何 Apple 平台上的现有代码库。了解如何通过将 SwiftUI 视图添加到 app 的层次结构,以及利用现有的数据模型等等,在任何 Apple 平台上采用 SwiftUI。
资源
相关视频
WWDC19
-
下载
(与SwiftUI相整合)
下午好 我是Tanu Singhal 我和我的同事Raleigh一起 今天跟大家分享 与SwiftUI相整合 (目标) 今天我们的第一个目标是 帮助你在你现有的app中 添加SwiftUI
接下来我们学习如何在SwiftUI中 嵌入UIKit、AppKit和WatchKit
稍后我们讲设置数据模型的策略 从而使数据模型 适用于SwiftUI
最后我们学习使用拖放、 粘贴模式和SwiftUI中的 焦点系统 从而使我们的app 能更好地整合到整个系统中
在app上托管SwiftUI内容 非常简单 (在你的app中 托管SwiftUI视图) 我们通过托管控制器来实现
托管控制器可以用于 把SwiftUI视图设置为 ViewController 或InterfaceController的内容
托管控制器在全部三个框架中都可用
首先让我们具体看一下 UIHostingController
UIHostingController 是UIViewController的子类
它有一个初始化程序 可获取一个 叫做rootView的单一参数
我们要把SwiftUI视图 传递到这里
一旦对托管控制器进行了初始化 它通过代码或Storyboard 呈现 就像任何其它视图控制器一样
对于Mac 我们有 NSHostingController 用于在NSViewController中 呈现SwiftUI内容
现在如果你是Mac开发人员 你可能并不总是希望呈现 整个视图控制器 也许你想在你现有的AppKit 视图等级中 嵌入一个小的SwiftUI视图
为此我们有 NSHostingView
NSHostingView 是NSView的子类 用于直接在AppKit视图等级中 呈现SwiftUI视图
如果你使用了自动布局 我们会自动遵守 你的SwiftUI视图的 内容尺寸偏好 并且你的布局将满足你的预期
当使用容器视图在你现有的 AppKit或UIKit视图等级中 嵌入UIHostingControllers 或NSHostingControllers时 也可以使用自动布局
对于watchOS开发人员 我们有WKHostingController
要使用它 你首先要创建一个子类 在子类中 我们会从主体中返回 SwiftUI视图 接下来进入Storyboard 并选择任意界面控制器或托管控制器
从身份检测器中 对WKHostingController 把类设置为你的自定义子类
现在托管控制器可以与任何 其它界面控制器一样使用了
如果你由于发生在 WatchKit上的变更 需要使主体无效 你可通过使用 setNeedsBodyUpdate 和updateBodyIfNeeded方法实现
在动态交互式通知中使用 SwiftUI内容也很简单
为此我们使用WKUserNotification HostingController 再一次 我们首先从主体中返回 SwiftUI视图 然后每次调用 didReceive通知方法时 这个主体都会被更新
要了解关于用SwiftUI 创建Watch app的更多信息 请查看watchOS上的 SwiftUI演讲
现在让我们看一个示例app 关于我们需要在哪里使用 托管控制器
几天前我出门去买一些植物
我学习了很多 关于不同的植物和树木的知识 我决定创建一个 把这些植物分类的app
我开始使用UIKit创建app 你在这里看到的是一个 标准的UIKit表视图控制器
然后我学习了SwiftUI 并使用SwiftUI为我的app 创建了详情视图
现在我还没有添加任何 从UIKitTableViewController 导航到SwiftUI的代码
让我们进行一次演示 看看我们该如何设置它 (关于在你的app中 托管SwiftUI视图的演示)
在这里我们有SwiftUI视图 用于呈现详情视图 这是当我们轻触表时 想要导航到的视图 让我们进入Storyboard
Storyboard将进入库 并查找托管视图控制器 让我们在Storyboard中 拖动它
我要选择表中的这个网格 按住Control键 并把它拖动到托管控制器中 选择显示跳转
现在我们需要在这个托管控制器中 添加内容 因此让我们打开另一侧的 表视图控制器
让我隐藏其中一些面板 留出更多空间
现在我要选择我们刚创建的跳转 按住Control键 把它拖到视图控制器代码中 这会创建一个 IBSegueAction
IBSegueActions 是Xcode 11中的新功能 允许你把Storyboard中的 跳转连接到 你的视图控制器代码 通过使用这些 你可以直接在你的目标视图控制器中 设置属性 而不需要使用 prepareForSegue方法
谢谢
让我们关闭Storyboard 因为我们主要看代码
在这里我要创建一个 SwiftUI视图的实例
这里的rootView被设置到了 PlantDetailsView PlantDetailsView 是我们的SwiftUI视图 我们所要做的就是 把这个rootView传递到 托管控制器的初始化工具中
现在当我们运行我们的app时 我们将可以从 UIKitTableViewController 导航到我们的PlantDetailsView PlantDetailsView在SwiftUI中
(关于在你的app中 托管SwiftUI视图的演示)
我们在这演示中看到了在app中 添加SwiftUI是多么容易
接下来我们要学习 在SwiftUI视图内 嵌入使用现有框架创建的视图
为此我们要使用 Representable协议 Representable协议允许我们 在SwiftUI中呈现UIViews、NSViews 和WKInterfaceObject (Representable 协议) 此外我们还可以在SwiftUI中 呈现视图控制器 通过视图控制器 Representable协议实现
Representable 协议有两个必需方法 Make方法和Update方法
Make方法 是创建你希望在SwiftUI中 呈现的视图或控制器的地方 而Update方法是把这个视图 更新为当前配置的地方
在初始化过程中 首先调用Make方法 然后再调用Update方法
可以多次调用Update方法 无论何时当SwiftUI 请求更新时都可以调用它
最后我们为你提供了一个 可选的Dismantle方法 你可以在视图或控制器被移除之前 在Dismantle方法中 放一些需要运行的清除代码
现在让我们看看这些方法的 Swift定义
请注意Make、Update 和Dismantle方法 在跨平台上看起来和用起来很相似
对于AppKit和UIKit 这些协议可用于 在SwiftUI中 呈现视图和视图控制器 对于WatchKit 我们可以使用 WKInterface representable协议 在SwiftUI中呈现 WKitInterfaceObjects的子集
你可以在developer.apple.com上 查询 所支持的WatchKitObjects的 完整列表
那么正如我们所提到过的 Make和Update方法 是在SwiftUI中 呈现视图的仅有的两个必需方法 然而视图通常很复杂 你想做的可能不仅仅是 简单地呈现它们 (视图的高级整合) 也许你想在SwiftUI中 暴露目标动作或委托
或你可能想从SwiftUI的 环境中读取内容 并做出相应的响应
了解你的视图上是否有动画 也很有用
为了让你能更好地整合 你的视图和SwiftUI 我们创建了 Representable情境
Representable 情境有三个属性 第一个是coordinator 帮助协调你的视图和SwiftUI coordinator 可用于实施通用模式 比如委托、数据源和目标动作 (Representable 情境) 下一个属性是 environment 帮助你读取SwiftUI的环境 可以是系统环境 比如色性或尺寸类 或明确的方向 或是app定义的自定义环境属性
最后是transaction属性 让我们的视图了解 在SwiftUI中是否有动画
Representable 情境可在视图、 视图控制器以及界面控制器中使用
现在让我们再看一下 我们之前看到过的 Representable协议图表
在Make和Update方法中 我们为Representable 情境传递了一个参数
这个情境已经拥有关于environment 和transaction的信息
然而如果你想使用 coordinator 你需要自己创建 可以通过 使用可选的Make Coordinator 方法实现
在初始化过程中 首先调用 Make Coordinator方法 然后是Make View 和Update View方法 从而当你配置你的视图时 coordinator 在情境中可用
通过例子来理解这些概念 可能容易得多
我们再看一下我们的植物app 这是我们刚才看到过的详情视图
它是在SwiftUI中创建的视图
我还在UIKit中 创建了另一个视图 用于呈现评级 我想要做的就是 在我的SwiftUI视图中嵌入 基于UIKit的评级控件
除此之外 我还想在 SwiftUI中添加一个标签 可以从我的评级控件中读取评级
这些全部都可以通过 UIViewRepresentable协议实现 让我们在演示中实现这些功能 (关于在SwiftUI中 嵌入UIKit视图的演示)
在这个项目中 我包含了一个 UIKitRatingsControl 它是基于UIKit的视图 渲染那些五星 它就是我们要在SwiftUI中 呈现的视图
RatingsControlRepresentation 其实是UIKit视图的包装器 它可以让我们在SwiftUI中 呈现我们的UI视图
我们还为UIViewRepresentable协议 添加了两个必需方法 即makeUIView 和updateUIView
在makeUIView方法中 我所要做的就是 创建我的UI视图的一个实例 也就是这里的 UIKitRatingsControl并返回它
通过这个代码 我可以开始在SwiftUI中 使用RatingsControlRepresentation了 让我们看看预览
这些星星的显示 通过在SwiftUI中 调用RatingsControlRepresentation 实现的 这反过来呈现了 基于UIKit的视图
然而请注意 所有星星都是灰色的 要根据评级正确设置突显 我们需要从SwiftUI中 读取这个评级 并把它设置到 我们的UIKit视图上
在我们的代码中 我们已经为评级添加了一个捆绑 因此我们可以 从SwiftUI中读取它
现在让我们进入 updateUIView方法 并在UI视图上设置评级
星星将立即按照我们所预期的那样 进行突显
并且这是我们从SwiftUI中 读取到的
谢谢
我们要进入实时模式查看 最后一个预览 在这预览中 我在SwiftUI中 包含了一个清除按钮 用于把评级更新为零
请注意当我轻触它时 会调用 UpdateUIView方法 并把评级上传到我们的UI视图上
我们还可以轻触星星修改评级
当我轻触这些星星时 右侧的标签并没有进行适当的更新
原因是我们的UI视图对于评级 是固有值 并且不会把固有值 传回到SwiftUI
为了解决这个问题 我们要使用目标动作模式 让我们继续并实施它
要使用目标动作模式 我们需要添加一个协调器 让我们在这里创建一个协调器 这只是个NSObject 是我们存储我们所感兴趣的值的地方 并且我们有一个初始化工具 用于设置我们所关心的值 就是这里的评级
接下来我们给评级添加了一个叫做 ratingChanged选择器 我们通过目标动作模式调用它 在这里我们仅仅把协调器的评级 设置为我们从UI视图中 所获取的评级
现在我们可以实施 makeCoordinator方法了
在这个方法中 我们仅仅是返回协调器的一个实例 并且我们从RatingsControl Representation中传递评级捆绑
最后我们可以在makeUIView方法中 使用这个协调器 并添加目标
这样 无论何时当在UIKit中 触发 valueChanged事件时 就调用协调器 ratingChanged方法
现在我们已经准备好 把它添加到我们的app中了 我要进入 PlantDetailsView
在这里调用 RatingsControlRepresentation
我们还可以设置一个 受UIKit支持的框架 让我们重新预览一下
我要进入实时模式
现在当我轻触这些星星时 值和文本标签如我们所期待的那样 进行了更新
(关于在SwiftUI中 嵌入UIKit视图的演示)
我们希望你对于在你的app中 使用SwiftUI感到兴奋 作为第一步 用SwiftUI内容 创建一些托管控制器 使用IBSegueActions把托管控制器 添加到你的app中非常简单 (试一下!) 如果你已经创建好 想要嵌入到 SwiftUI视图等级中的视图 你可以了解一下 Representable协议 最后一定要利用 Representable情境 实现更高级的功能
接下来Raleigh会讲 整合数据模型和SwiftUI (与你的数据模型相整合)
谢谢Tanu
我是Raleigh Ledet 我既是SwiftUI 又是AppKit工程师 你们已经了解在你现有的app中 迅速添加 SwiftUI视图有多么容易 并且我们已经得到了数据 但我想讲的是如何真正把它 与你的数据整合到一起
你在Tanu的演示中所看到的是 我们把植物数据模型 传递给我们的根SwiftUI视图 这非常棒 因为SwiftUI视图 能取出适当的属性 并且我们能对这些属性进行渲染 然而这更应该叫做单次操作 (静态数据) 因为我们的数据模型是存在于 SwiftUI框架之外 (动态数据) 这意味着如果我们的数据模型 发生任何变更 也许是云发生变更 或甚至是用户发生变更 SwiftUI将不了解这些变更 并且它也不会对我们的数据内容 进行重新渲染
我们的方案是 BindableObject 数据模型 它是一个非常简单的协议 你所要做的就是公开发布一个 didChange发布器
一旦你实施了 didChange属性 你就在SwiftUI视图中遵守了 BindableObject协议 就是我们之前引用数据模型的那个 SwiftUI视图 现在我们可以使用 @ObjectBinding包装器
它告诉SwiftUI我们正引用 BindableObject 然后它就知道它可以为这个视图订阅 BindableObject 现在无论何时当你的数据发生变更时 didChange发布器 都会给它所有的订阅者 发布有数据发生了变更 当然 其中一个订阅者 是SwiftUI 现在SwiftUI自动了解 哪个视图正在引用你的数据模型 并需要更新
此外
我们可以使用$加数据 并可以对数据模型 使用捆绑 这将使我们拥有直接重写 数据模型的权限
因此现在 无论何时当我们做修改时 也许是修改文本字段 这些修改都将直接 在我们的数据模型中进行更新
因此正如你所看到的 BindableObecject 协议非常简单 再一次 你只需要实施一个属性 并且它有很高的灵活性 它可以使许多发布器 与你正在使用的 任何一种通知系统一起 记录在你的数据模型中所发生的变更
并且这里的关键点是我们想确保 你的数据模型在你的app中 保持数据的单一数据来源
这在SwiftUI中非常重要 我们总是希望你的数据模型 或你在SwiftUI中的任意状态 都只有单一的事实来源
与声明性视图等级一起 就不再需要给同步数据 写入视图控制器了
现在让我们在演示中看一下
Tanu过来找我的时候 她告诉了我关于植物的想法 我非常激动 并且我想参与并提供一些帮助 我想从写Mac版app开始
因此我们就开始写app 她做iOS版 我做Mac版 然后我们达到了相同的目标 当我们看到SwiftUI时 我们感到惊叹万分 因为我们可以使用 SwiftUI快速前进 并写我们的详情视图
那么在这里我们正在 运行同一个app 只不过现在是在Mac上
那么在这里 左侧有NSTableView 右侧有同样的详情视图
但现在我们想再进一步 把它真正与我们的数据模型 整合到一起 从而我们可以修改我们的详情视图 并变更反映到我们的数据模型中
这是我们的数据模型 你可以看到 它是个非常简单的数据模型
我们所拥有的就是一些植物 嗯 我特别想指出一点
无论何时当植物发生变更时 我们都会发布一个 PlantsDidChange通知 我们这样做是为了 让视图控制器中的表视图 可以监听变更 并在表视图中重新加载数据 但因为我们已经发布了一个通知 我们要使用那个通知来实施 didChange BindableOBject
那么这是我们对 didChange的实施 我们对PlantsDidChange使用了 NotificationCenter发布器 我们使用self作为 我们想要监看的对象 现在我想指出另外一点
对数据的修改需要通知 主线程上的SwiftUI 需要进行修改 因此我们用receive(on) 操作器以确保 我们的发布器向主线程上 所有的订阅者发布通知
现在我们的数据模型已经准备好了 我们可以转向详情视图了 在这里你可以看到我们引用了 我们的 PlantsDataModel 现在我们可以添加
我们的 ObjectBinding了
现在我们正在使用 ObjectBinding包装 我们要向下进入… 我们在isEditing状态上现有视图 但我们目前使用的是EmptyView
我已经在EditablePlantsView中写好了 我想指出的是 在这里我们使用了$前缀 从而我们可以对指定植物索引 进行绑定
现在我们要重新运行app
现在通过那个简单的修改 app运行起来跟以前一样 当我们点击编辑按钮时 我们现在可以编辑各种属性了 你可以看到立即更新了表视图 我非常喜欢夏威夷木槿 我要把它评为五星 那么现在我们已经直接 在我们的数据模型中更新了数据 我们随时可以重新回到数据模型中
(关于与我们的数据相整合的演示)
如你在那个演示中所见 我使用了 NotificationCenter 因此我只需要使用NotificationCenter 发布器即可 但我们还有其它类型的发布器 比如关键值观察发布器
遵守KVO的任何对象都有一个 关键值观察发布器 你可以通过对关键值函数 使用发布器来获取它 但让我们再看一个更有意思的例子
在这个例子中 我们有一个类用于 在用户默认中监看 用户默认所发生的变更
有意思的是 我们给每个用户默认都创建了一个 发布器 一个用于userOption1 一个用于userOption2 但我们把它们合并到了一个发布器中
并应用到我们的 didChange属性
因此现在 无论当userOption1或 userOption2发生变更时
didChange合并发布器 都将在SwiftUI发布修改 并且SwiftUI将更新 我们的视图
(合并) 所有发布器都经由合并框架 并且那还有更多发布器 你可以查看它们 并且合并框架是一个很强大的新框架 它是一个统一的声明性API 用于随时间处理值 (合并) 除了你在合并操作器看到的发布器 还有大量不同的操作器 执行复杂的合并或把不同的发布器 打包到一起
我强烈建议你观看 在实践中合并演讲
然而我想指出另一个指定发布器 即PassthroughSubject
如果你的数据模型遇到这样一种情况 合并框架中没有任何一个发布器 适用于你的情况 你可以使用PassthroughSubject 就像我在核心数据示例中所做的那样 如果你有一个核心数据app 那么你就已经在使用 NSFetchedResultsController 来从数据库中取出数据了 并且NSFetchedResultsController 允许你提供一个委托 以帮助协调 你需要实施的其中一个委托消息是 controllerDidChangeContent 当数据库中的数据发生变更时 它会告诉你 当数据发生变更时 我们需要让SwiftUI知道 因此我们抓取我们的didChange PassthroughSubject发布器 我们要告诉它手动发送变更 现在SwiftUI把它看作是 其中一个订阅者 并更新你的全部视图 (处理数据流的工具) 我主要讲 BindableObject 但还有许多工具可以帮助你管理 SwiftUI之内和之外的数据 SwiftUI中的数据流 是一场很棒的演讲 非常具体地讲了所有的数据工具 同时讨论了何时使用 哪种类型的工具合适
(与系统相整合) 现在当然了 当你运行SwiftUI界面时 你并不是只需要思考 与你的数据模型相整合 你还需要思考 与系统中其余的东西相整合 与iOS和macOS的拖放相整合 与tvOS相整合
以及也许是与watchOS上的 数码表冠相整合
让我们从item提供器开始讲 item提供器是一个强大的技术 由基础框架提供 为你提供一种围绕你的app 以不同形式移动数据的方法 它还是用于帮助在各进程间 转移数据的工具
从大体上说item提供器 是通用类型识别器的一个集合 描述你的item可以表示为 哪种类型的数据 当然了 你需要按照请求 为那个类型提供数据
请记住 之前在演示中我指出 我们需要在主线程上修改数据 而item提供器是异步的 因此当你让数据 形成item提供器时 你需要确保你实际上修改了数据 或让发布器在主线程上进行发布
我们使用item提供器和拖放 因此你可以使用onDrag修改器 把视图作为拖拽源 那么现在当用户开始在你的视图上 进行拖拽时 我们将调用闭包 然后你就可以 提供一个item提供器 它会 提供与那个视图相关联的数据 然后我们会自动渲染你的视图 并把它用作DragImage (拖放) 要接受一个释放 你可以使用onDrop修改器 通过onDrop修改器 你可以传递一些 通用类型识别器字符串 这个字符串描述你可以在你的视图上 接受的任意一种数据 如果用户在你的视图上释放
那种类型的数据 我们将自动调用你的动作闭包 并提供一些 可形成那个类型的item提供器 当然我们还将告诉你 在你的视图中 发生释放操作的准确位置
onDrop修改器还有另一个变量 它获取的是委托闭包 而不是释放闭包 并且当释放在你的视图中四处移动时 委托为你提供关于释放过程的 更大的可见度 比如你可以在用户实际释放 并实施释放动作之前获得游标的位置
我们还在pasteboard中 使用item提供器
因此比如说如果你想接受 一个粘贴命令 你可以使用 onPaste命令修改器
类似于onDrop修改器 你提供一些通用类型识别器 然后就可以接受粘贴了 当用户在你的视图上进行粘贴时 我们将提供一些item提供器 然而我想指出一些 使onPaste与onDrop 完全不同的东西
第一个是 闭包中没有位置参数 这对于这里所发生的操作至关重要
当你拖放时 用户直接通过游标或触摸位置标定 应该接受释放的视图
但粘贴命令更间接一些 用户要么选择从菜单中粘贴 或也许是使用键盘捷径 或使用iOS中的新手势
我们了解 粘贴命令即将在哪个视图上执行的 方式是通过焦点系统 焦点系统是一个很重要的工具 它是用户用于导航不同的UI元素 并通知我们没有特别指向的动作 应该发生在哪里
它在Mac上很有用 当然是对键盘输入 和菜单动作命令 在iOS中 是对键盘命令 此外还有复制-粘贴和撤销-重做 这两组新手势 (焦点) 在tvOS上尤其重要 在这里焦点是我们如何决定 用户想在哪里实施 SiriRemote按钮动作
对于watchOS 我们使用焦点 来决定向哪里发送表冠事件
它的运作方式是 在某一时刻你拥有视图等级 其中一个视图将被作为焦点视图 当用户实施间接动作时 比如旋转表冠 我们会检查焦点视图是否 有针对那种命令的视图修改器 在这个例子中是表冠命令 如果它有 我们会调用适当的闭包 如果它没有 我们会沿原型向上 尝试找到一个拥有表冠命令的 原型视图 并调用适当的闭包
SwiftUI将在每个平台上 恰当地处理 从一个视图到另一个视图的移动焦点
你所需要做的唯一一件事就是 让我们知道 哪个SwiftUI视图 会成为焦点视图 你可以通过focususable 修改器实现
除了leaf控件 比如文本字段
SwiftUI视图 默认不会成为焦点视图 因此你需要使用 focususable修改器 和Passthrough告诉我们 这个视图可以成为焦点视图 你可以视需要传递一个 可供我们调用的闭包 当你的视图得到或失去焦点时 我们通过调用它来通知你 你可以使用这个来更新你的UI 从而为用户提供视觉反馈通知他们 (命令) 我们有许多命令 如onExit 和onPLayPause 这些例子来自于tvOS 当使用Siri Remote时 但我现在要讲的是 通用的onCommand修改器 这是你用于指示动作的工具 从Objective-C-style 动作选择器 比如说从菜单传送到第一个响应器 或从工具栏按钮 同样地被传送到第一个响应器 再一次 这是它在iOS上的用法
并且它们是可链接的 因此假如说如果你的视图可以接受 三个菜单项 你还可以给你的视图附加三个 onCommand修改器 每个都有适当的选择器
(撤销和重做) 现在我知道你们的app 全都已经有很强大的 撤销和重做支持了 在SwiftUI中 我们所用的UndoManager 与你们已经在使用的一样
并且 在绝大部分情况下 当你向app中 添加新SwiftUI时 你不需在UndoManager中 执行任何新操作 特别是当你的撤销注册 在较低层上接近数据模型时执行时
然而 如果你需要使用 UndoManager 你可以通过environment 属性包装器获取 通过UndoManager 密钥路径
(Objective-C整合) 现在SwiftUI很明显是一个 基于Swift的API
但我们知道你已经拥有大量 Objective-C代码了 Swift中的 Objective-C 已经可以很好地整合到一起了 同样地 你也可以用SwiftUI 处理Objective-C代码
适用标准的 Objective-C/Swift整合规则 基本上 当涉及 SwiftUI时那意味着 你需要包装Swift中的 托管控制器 或托管视图
在这个例子中 我们要包装一个托管控制器 我要给UIViewController 做一个子类 我把它放在 Objective-C属性中 这会允许我稍后在 Objective-C实施文件内 实例化这些Swift类
现在 在我们的Swift实施内 我们可以实例化 UIHostingController 并把它传到适当的 SwiftUI RootView中
现在我们有 UIViewController 我们可以从Objective-C 实施文件中使用它 就像其它任何 UIViewController 在这个例子中 我们只是呈现了它
类似地 你也需要包装你的数据模型
那样我们就可以实施 BindabelObject协议
那么这里我们有个简单的 Swift类 我们要 通过这里的NotificationCenter 发布器实施BindableObject协议 这是个例子 让我们假设ObjCDataModel 已经发布了 NotificationCenter通知 那么我们只需要把它引用到 ObjCDataModel即可 它的运作方式是
在WrappedHostingController中 你要给ObjCDataModel传递一个 指示器 在你的托管控制器中 你可以创建 WrappedDataModel 并把它分配为你的ObjCDataModel 并把你的WrappedDataModel 传递到你的 SwiftUI rootView 仅通过这两个简单包装的类 你现在已经可以把SwiftUI 和Objective-C代码 无缝整合到一起了
因此正如你所看到的 开始在你的app中 使用SwiftUI 非常简单 当你添加新UI时 请开始使用SwiftUI
我们明天上午11点有一场讨论会 在你的app中 尝试使用SwiftUI 如果你有任何疑问 请参加我们的讨论会 我们非常高兴能与你们沟通 我们对SwiftUI感到非常激动 我们已经迫不及待要看到你们 能用它做出什么样的app 谢谢大家 请享受余下的会议时光
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。