Ask Apple问答汇总之SwiftUI其二

653 阅读13分钟

近期,苹果开发者网站发起了Ask Apple活动,邀请开发人员直接与苹果专家沟通。

活动时间是2022年10月17-21日,目前活动已结束。

苹果为我们保留了本次活动中所有内容供开发者查阅。

我认为有必要在这里对一些感兴趣相关专题中问答内容进行汇总并翻译,供大家参考。

由于水平有限,文中的翻译可能有些不准确或有些小错误,还望大家在阅读过程中理解。如果您发现错误或有更好的想法,欢迎指正🙌🏻

本篇是关于SwiftUI的问答内容汇总。由于内容较多,为了控制篇幅,我会将所有该专题内容整理为三个部分,本文是第二部分。📚

这里第一部分:Ask Apple问答汇总之SwiftUI其一

SwiftUI

截屏2022-10-25 09.36.04 2.png

何时可以自定义NFC标签读取屏幕?

Developer:

何时可以自定义NFC标签读取屏幕?目前只有 1 个文本视图可用。我们希望能够自定义此视图,而不是:)能否在以后的版本中考虑一下?

Apple:

请做文件反馈!feedbackassistant.apple.com(如果您已经提交了申请,您可以在帖子中发布FB编号吗?谢谢!)

Developer:

我刚刚提交了反馈,FB编号是:FB11701684

当详细信息视图需要绑定时,应如何使用navigationDestination(for:)

Developer:

当详细信息视图需要绑定时,应如何使用navigationDestination(for:)?传递给NavigationLink的值必须是可哈希的,因此我不能使用绑定。这意味着我必须传递一个item ID,然后在navigationLink(for:)中手动从该 ID 重建绑定。这是正确的方式吗?

Apple:

传递 ID 并构造绑定是一种合理的方法。

我希望得到一个反馈,其中包含有关您的用例的详细信息,以便我们可以考虑如何使其更好。

Developer:

我用了这个,但我可能做错了,感谢您的评论 -- 我的caseMO是一个CoreData托管对象(抱歉缺少空格):

enum CaseRouter: Hashable, Codable {
    case dtg(CaseMO)...         navigationModel.navigationPath.append(NavigationModel.CaseRouter.dtg(caseMO)....navigationDestination(for: NavigationModel.CaseRouter.self) { value in
        switch (value) {
        case .map(let caseMO):
          LocationView(caseMO: caseMO)
        case .dtg(let caseMO):
          DTGView(caseMO: caseMO)
        }
    }
}

如果App仅设计为数据读取器,是否可以禁用新文件的创建?

Developer:

在 macOS 上使用 SwiftUI App LifecycleDocumentGroup时,如果App仅设计为数据读取器,是否可以禁用新文件的创建?

Apple:

DocumentGroup应提供用于创建阅读器App的初始值设定项。

例如:

developer.apple.com/documentati…

这将允许打开该内容类型的文件,但不能编辑它们。

MVVM是否仍适用于SwiftUI

Developer:

MVVM是UIKit时代的一种常见架构,根据数据显示的视图是从单独的视图模型类中获取的。这是否仍然适用于 SwiftUI,还是"结构"本身现在被视为viewModel

Apple:

SwiftUI 试图与应用的整体架构保持不可知。虽然,在传统的视图模型意义上,我不建议将视图(结构本身)视为视图模型。这可能会产生一些后果,例如使视图的可重用性降低,并将业务逻辑与 SwiftUI 视图的生存期相关联,这将使处理业务逻辑比需要的更困难。 简而言之,我们不建议使用视图作为视图模型。但 SwiftUI 确实提供了实现经典 MVVM 架构的工具(例如,状态对象、观察对象)

Developer(路人Lowell):

是否仍然支持在 SwiftUI 视图中使用@Published属性?最近的 Xcode 版本一直在抛出紫色视图更新警告。developer.apple.com/forums/thre…

Apple:

我们收到了一些反馈,并相信这些紫色警告已在最近的测试版中得到修复。 @Lowell 您正在运行最新的种子吗?

Developer(路人Lowell):

我正在使用14.1 beta3 (14B5033e),仍会收到很多(警告)。

Apple:

我强烈建议更新到最新的测试版。我认为那是一个月或更长时间以前的(版本)

Developer(路人Lowell):

据我所知,这是最新的测试版,看看开发人员网站和第三方xcodes工具。也许我错过了一些东西

Apple:

哦,这就是你正在谈论的Xcode测试版号码,对不起。您正在部署到哪个操作系统并看到问题所在?

Developer(路人Lowell):

是的,很抱歉没有说清楚。实际上,由于我现在开始处理我的项目,因此我无法重现警告。但是它在iOS 16.1上管用,不确定我自昨天以来更改了什么来解决这个问题😅

Apple:

很高兴听到(这个消息)!如果您看到更多,请随时提交。

关于视图在意外时间触发的问题

Developer:

在我的应用程序中,我在 UIHostingControllers中托管 SwiftUI 视图,这些视图都植根于一个 UITabBarController

最近,我注意到 SwiftUI 视图在意外时间触发了 ,例如在创建UITabBarController时,而不是在视图本身出现时。我想知道

  1. 对于像这样在UITabBarController中托管的 SwiftUI 视图,究竟应该在什么时候调用 onAppear
  2. 当视图在这样的 UITabBarController中托管时出现时,执行代码的推荐方法是什么?

Apple:

在其他类型的 UIHostingController 中使用 UIViewControllers 时,可以通过调用宿主控制器的方法来触发视图加载提前发生。

对于"non-lazy"视图(如LazyVStack),一旦以懒加载形式初始化了UIHostingController的视图,就会调用onAppear。在托管控制器视图调用layoutSubviewssizeThatFits最终可能会初始化视图。

因此,如果您看到视图在tab controllers的初始化方法中初始化,我会查看该初始化方法正在做什么,并且通常尝试将该 init 中的任何工作移动到选项卡控制器的viewDidLoad 中。

当键盘关闭时,键盘曾经占用的空间是否应被删除?

Developer:

FocusState 变量设置为零时,当键盘关闭,键盘曾经占用的空间是否应被删除?在iOS 15上,情况就是这样,但在iOS 16上却没有,只是想知道我是否需要在iOS 16上做一些额外的事情来获得删除的空间?

Apple:

这取决于具体情况,但我认为我不认为我期望iOS 15和16之间会有变化,因此值得提交有关它的反馈报告。如果可以使用示例代码重现问题,则在反馈中包含该问题将非常有帮助。

Developer:

(这个问题)看起来和我的问题相当接近

appledeveloper.slack.com/archives/C0…

Apple:

是的,这听起来确实像是一个类似的问题。我们正在查看该线程中提到的反馈报告。

Developer:

struct ContentView: View {
  @State var text: String = ""
  @FocusState var focused: Bool

  var body: some View {
    ScrollView {
      TextField("Test", text: $text)
        .focused($focused)
      Color.pink.frame(height: 2000)
    }
  }
}

如果您创建一个新项目,将其用作内容视图,请在iOS 16或16.1上运行 点击顶部的字段,滚动到底部,点击键盘上的返回

FB11701808

有没有可能发现解决这个问题的方法?

NavigationStack路径参数一起使用导致的问题

Developer:

我们将新的 NavigationStack 与路径参数一起使用,但是当用户在stage manager中将窗口大小从Regular调整为Compact时,在''转换''路径时遇到了麻烦。 在常规宽度中,我们有一个侧边栏,详细信息视图中有一个导航堆栈。在紧凑宽度中,我们有一个选项卡栏,每个选项卡中都有一个导航堆栈。

Apple:

目前,最好的方法是生成一个导航状态模型对象,该对象保存导航状态的规范表示形式,但可以用于专用于正常和紧凑显示的编程绑定。例如,在模型中有多个路径,每个选项卡对应一个路径,但在拆分视图中仅投影其中一个路径作为详细信息。

Developer:

这很有趣。从未考虑过拥有多条路径。我们目前有一个在所有选项卡和详细信息导航堆栈之间共享的路径实例。 这需要我们添加以下内容:

.onChange(of: rootNavigationManager.selection) { _ in
    guard path.count > 0 else { return }
    path.removeLast(path.count)
}

但也许你的解决方案更好🤔

Apple:

我真的很喜欢使用一个共同的底层事实来源,并将其投射到UI的需求中。这特别好,因为我可以对该模型进行单元测试,以确保常规和紧凑的投影是一致的。

Developer:

好主意。我会试一试,看看它会把我带到哪里。谢谢你帮我,我真的很感激!

请让我知道我如何更有效地提问

Developer:

以非常感谢你们!!. 如果一些工程师或技术支持人员在Apple开发人员论坛上回答问题,那将非常棒。许多问题仍未得到解答。我已经提交了反馈意见,并联系了DTS。DTS 会查看工单的状态并说明它们已打开。我为WWDC 2021创建了反馈,这些反馈仍然保持开放状态,没有评论。 因此,我感到无助,因为我已经用尽了所有选项(Apple开发人员论坛,反馈,DTS)。请让我知道我如何更有效地提问。 一些反馈 ID: FB11661364, FB10128110, FB11565614, FB11517536, FB11428998, FB11275037

Apple:

嗨,Muthuveerappan!有时我们无法直接回复反馈,但我们确实很感激。事实上,了解您尝试使用我们构建的 API 做什么以及它们不足之处至关重要。非常感谢您抽出宝贵时间发布,特别是发送反馈。

Developer:

谢谢,当你们有时间看一下它们时,我已经附加了示例代码,视频,复制的步骤😊🖖

在非线性位置(2轴)渲染带有圆形图像的自定义屏幕的最佳方法是什么?

Developer:

在非线性位置(2轴)渲染带有圆形图像的自定义屏幕的最佳方法是什么?我目前正在使用ZStack,其中的图像是用偏移量渲染的,这样我就可以将它们放置在我想要的位置,但我不知道这是否是最有效的方法。

Apple:

只要它的性能足够好,可以顺利地处理你的用例,这对我来说似乎是一个完全合理的实现。如果您遇到性能问题/试图大幅缩放正在绘制的图像数量,您可能还需要查看 .drawGroup()Canvas API,它们都可用于更密集的绘制。

有什么好的方式将NavigationSplitView设为折叠状态

Developer:

你好!我已经开始采用NavigationSplitView,并且非常喜欢它。在某些情况下,我想根据视图是否折叠来做出决定(例如,如果展开,则在详细信息视图中显示消息,或者如果折叠,则显示警报或其他指示)。我是否可以假设,如果水平大小类是紧凑的,它就会折叠?还是有更可靠的方法?

Apple:

我很高兴你喜欢它! 紧凑的水平大小类对应于折叠的NavigationSplitView。 我有兴趣更明确地说明这一点,所以希望得到一个带有您特定用例的反馈。

大量UITextFields在SwiftUI中使用导致CPU飙升的问题

Developer:

我有一个包含 132 个 UITextFields的 SwiftUI 视图;我知道这是很多textfields,但这是业务逻辑的一部分。 经过大量的挣扎和内存泄漏测试,我设法让它工作,但是从一个UITextFields到下一个UITextFields的焦点感觉不够流畅,似乎每当我在其中一个UITextFields中键入一个字母时,我的CPU使用率就会飙升到70-100%。 我也相信我的一些观点在检查UI时出现两次;不确定为什么。 我有一个我想分享的演示项目。

在哪里可以链接演示项目?

作为参考,我在UIKit中100%实现了相同的视图,并且它不会受到任何性能问题的影响。

Apple:

如果您在使用 UITextField 的 iOS 上遇到性能问题,则可以尝试避免每个视图都是TextField,并在默认情况下呈现为文本,并在点击该文本时动态切换到TextField

Developer:

这听起来是个好主意。我必须实现它,看看它是否会感觉自然。

多个视图之间共享数据的最佳方式是什么

Developer:

如果此数据来自 API 响应,则在多个视图之间共享数据的最佳方式是什么?
我在 ContentView 中使用环境对象作为所有视图的包装器,在每个视图内部,我使用@EnviromentObject来访问此数据,这是这种情况的最佳方法吗?这种方法中唯一的问题是当我追加新数据时内存使用量增加。

Apple:

@EnvironmentObject/environmentObject可能是跨视图层次结构共享同一模型的最佳工具。使用它们应该只创建一个实例,然后在子视图中可读。这不应该增加内存使用量(如果是,请提交反馈)。如果将越来越多的数据附加到模型对象,则可能会增加内存使用量;无论使用哪种 SwiftUI,这都是很正常的。如果发生这种情况,一种克服的技术是在磁盘上卸载一些数据,并将最相关的数据和标识符保存在内存中,以便能够完全取回其余数据。

如何使用工具栏使键盘位置显示在键盘上方

Developer:

如何在不使用NavigationView的情况下,使用工具栏使键盘位置显示在键盘上方?如果我在NavigationView之外使用它,除非我在NavigationView中设置它,否则它不会显示

Apple:

如果使用NavigationView,请将工具栏修饰符放在NavigationView中。如果不使用NavigationView,则带有键盘位置的工具栏修饰符应适用于视图中的任意位置。

Developer:

好吧,我在ContentView中尝试过它,它正在工作,但在工作表中不起作用,所以是的,它使用NavigationView并没有用,但在工作表视图中不起作用

Apple:

请针对该问题提交反馈。 但是,如果您的工作表位于NavigationView之外,则可以尝试将其移动到NavigationView中,以查看是否有帮助。

Developer:

如果我在工作表内添加了NavigationView,它会正常显示,因此我将针对此问题提交反馈

关于SwiftUI的第二部分就到这里啦,还有最后一个部分,我会尽快整理出来,敬请期待!⏳