Ask Apple问答汇总之SwiftUI其一

182 阅读9分钟

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

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

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

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

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

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

SwiftUI

截屏2022-10-25 09.36.04 2.png

NavigationSplitView故障问题

Developer:

使用NavigationSplitView,当详细信息是列表时,侧边栏的打开和关闭会重新加载整个详细信息视图,从而产生故障。单元格不会展开或收缩,它们只是用新框架重新加载,然后滑动到位置。我认为同样的错误出现在UITable / CollectionView中(我认为由hood下的列表使用)。是否有一些解决方法? 如果详细信息视图是堆栈,则 UI 会完全收缩和扩展。

Apple:

您是否尝试过iOS 16.1 bata?我们在16.1中修复了与NavigationSplitView相关的许多问题。

关于为共享表添加“原生”SwiftUI 支持

Developer:

是否有计划在不使用 UIActivityView控制器的情况下为 iOS 系统共享表添加“原生”SwiftUI 支持

Apple:

现在可以使用!请查看共享链接 developer.apple.com/documentati…

Developer:

可敬的,感谢!😊

.contextAction修饰符会重现回来吗

Developer:

在早期的 iOS 16 和 macOS 13 测试版之一中,我们看到了一个新的.contextAction修饰符,后来被删除了。是否有任何建议来检测列表中的行选择,类似于“NavigationLink”,但不导航到另一个视图(例如,显示工作表或从列表中选择一个选项)?按钮在iOS和iPadOS可以很好适配,但在macOS上适配得不是很好。此外,.contextAction支持多选。它会回来吗?

Apple:

查看上下文菜单修饰符的主要操作参数。(这里是文档)。该 API 还具有一个用于选择类型的参数,允许您支持多选。

Developer:

感谢你,Harry!

是否有在 SwiftUI 视图中测试@State变量的推荐方式?

Developer:

是否有在 SwiftUI 视图中测试@State变量的推荐方式?还是将这些变量重构为视图模型的唯一方式?

Apple:

如果在同一视图中,您有一堆相互依赖的@State属性,则最好将其提取到其自己的结构中,以便您可以测试代码中的不变量。 将其提取到自己的视图模型中也是一种策略,但这不是必需的。

关于TextFields

Developer:

您好,首先非常感谢和祝贺这一举措。我的问题是关于TextFields的。 假设我们要创建一个类似于iMessage的视图,您可以在其中看到一个消息列表(与本例无关)和视图底部的文本字段。当用户点击文本字段时,键盘的工具栏中将显示一个文本字段。 我尝试在工具栏项组中添加一个文本文件(placement:.bottomBar)和工具栏项目组中添加第二个文本文件(placement:.keyboard),然后在@FocusState变量的帮助下,我可以隐藏一个并将焦点更改为键盘。这有点笨拙,我不认为有2个TextFields是好的实现方式。同样,按照此方法,@FocusState变量无响应,并且无法将其设置为 nil(返回到上一个视图且不会移除键盘)。 是否可以在纯 SwiftUI 中完成(不使用 UIKit)? 你能给我一些指导来完成它吗?

Apple:

一般来说,我建议使用这种实现方式:

.safeAreaInset(edge: .bottom) {
  MyTextField()
}

用于永久位于底部的文本字段。然后,您可以使用焦点状态来自定义其背景,无论其是否聚焦。 希望这适用于您的设计。

如何在来自不同subtrees的两个子视图之间共享状态

Developer:

如何在来自不同subtrees的两个子视图之间共享状态(例如可观察对象),而不被动地调用顶级视图的视图正文? (假设我可以在父视图中具有状态对象,并通过环境对象传递对象。但是,如果内部的 @Published 属性发生更改,则父视图及其subtree也将重新计算)

Apple:

EnvironmentObject是一个很好的工具。如果您不希望父级也更新,则可以在创建对象时不使用@StateObject@ObservedObject

Developer:

意思是只是顶层视图中的一个属性,但仍然传递到 .environmentObject()

Apple:

没错~

Developer:

感谢~

是否可以检查NavigationPath,以查看我是否通过 SearchView 到达了某个视图

Developer:

我很高兴看到新的 NavigationStack/NavigationPath,它对我来说运行良好。 我想知道我是否可以检查NavigationPath,以查看我是否通过 SearchView 到达了某个视图(作为一个示例)。 我确实找到了一个使用NavigationPath.CodableRepresentation实现的想法,但我担心这可能不是检查我的异构堆栈元素的最佳或最可持续的方式。 谢谢!

Apple:

目前没有内省NavigationPath的方式。如果您需要知道路径的内容,一个好的方法是使用同构路径,如下所示:

@State private var path: [MyEnum]

然后,您的navigationDestination将打开枚举类型。(已编辑)

关于Swift图标拖动事件监听问题

Developer:

我有一个 Swift 图表,在其中监听拖动事件并在拖动期间显示规则标记。在拖动过程中,y 轴刻度变大。在我的情况下,它不拖动时从0到75,在拖动期间从0到100。有没有办法防止这种情况?

Apple:

默认的 y 刻度会自动考虑规则标记的 y 值及其周围的任何注释。您可以使用以下命令修复 y 尺度域:

.chartYScale(domain: 0 ... 75),或者尝试确保规则和规则周围的任何注释不超过 75。

关于 iOS 16.x 中键盘安全区域的问题

Developer:

我们的用户继续报告 iOS 16.x 中键盘安全区域的问题。要点是键盘关闭根本不更新安全区域,这会在我们的UI中留下大键盘大小的孔。对于我们(以及我们所知道的其他一些社区成员)提交的反馈问题,系统是否有任何更新?

为了使这个问题不那么模糊,我从归档的反馈中复制了一些步骤来重现这个问题。

若要进行测试,请在随附的项目中尝试以下步骤:

  1. 通过选择按钮显示工作表
  2. 通过关注文本字段来触发键盘
  3. 开始以交互方式缓慢地关闭工作表 此时,系统将从文本字段中重新分配焦点并关闭键盘。
  4. 取消交互式关闭手势

请注意,两个 SheetView 子项(黄色和绿色)现在都位于键盘所在的位置,因为它尊重键盘的安全区域。

​```
import SwiftUI
@main
struct Application: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}
struct ContentView: View {
    @State var isPresented = false
    var body: some View {
        Button("Present") {
            isPresented = true
        }
        .sheet(isPresented: $isPresented) {
            SheetView()
        }
    }
}
struct SheetView: View {
    @State var text = ""
    var body: some View {
        ZStack(alignment: .bottom) {
            Color.yellow
                .overlay(alignment: .top) {
                    TextField("Type something here...", text: $text)
                        .padding()
                }
            Color.green
                .frame(height: 100)
        }
    }
}

Apple:

你能链接到你提交的反馈吗?

Developer:

👋🏻FB11618967

Apple:

感谢,我会看的。

Developer:

我还提交了一个与此类似的问题(发布以继续)

FB11701808

是否可以根据模型的更改对视图进行动画处理

Developer:

你好!是否有任何其他方法可以根据模型的更改对视图进行动画处理,而无需使用 onChange 修饰符? 我的代码是这样的:

@EnvironmentObject var model: MyModel
@State var isAnimated: Bool = false
var body: some View {
	
	.onChange(of: modle.state.aChange( { value in
		withAnimation() {
			self.isAnimated = value
		}
	}
}

Apple:

您可以使用 .animation(value:)直接使用模型(无需额外的@State属性)对更改进行动画处理修饰语:

.animation(.easeInOut, value: model.state)

这将对由 model.state 更改导致的任何更改进行动画处理。

Developer:

多谢,我会试试看!

如何在 iOS 16 中显示与动态内容高度匹配的底部工作表?

Developer:

如何在 iOS 16 中显示与动态内容高度匹配的底部工作表?简言之,我想在presentationDetents中使用视图高度。

Apple:

谢谢你的问题。目前这是不可能的,但这是我们感兴趣的。

将来是否会有@ToolbarBuilder或者对if condition { ToolbarItem(a) } else { ToolbarItem(b) }更好的支持?

Developer:

将来是否会有@ToolbarBuilder或者对if condition { ToolbarItem(a) } else { ToolbarItem(b) }更好的支持?

Apple:

首先你可能永远没法使用@ToolbarBuilder,但是我们会提供@ToolbarContentBuilder,它会在iOS 16获得一些新特性。

ToolbarContentBuilder的支持(及其它)和符合ToolbarContent的自定义类型现在支持动态属性,如@Environment/@EnvironmentObject

Developer:

感谢++!这正是我需要的。

是否有任何关于何时/是否有多个场景的指导或示例?

Developer:

👋🏻早上好!我对 SwiftUI(及苹果开发!) 很陌生 – 我的问题是关于场景的。

在我一直在探索的几乎所有教程和其他示例代码库中,只有一个WindowGroup场景,所有实际操作都嵌套在InentView()中 - 是否有任何关于何时/是否有多个场景的指导或示例?还是大多数应用只是嵌套在单个窗口组中?

Developer(好心的路人):

您最需要多个场景来构建多个场景,例如“页面”或“数字”应用

Apple:

多个场景对于构建更复杂的应用程序非常有用,尤其是在 macOS 上。例如,您可能希望有一个同时定义DocumentGroup DocumentGroup 的应用程序,或者一个具有DocumentGroup 和辅助Window场景的应用程序。场景的内容视图定义了场景创建的窗口中的视图内容,但场景本身定义了应用程序的整体结构。

Developer:

多谢你们所有人,很有帮助

那么每个iOS应用程序都是一个单一的场景吗?

Apple:

它不一定是必须的。在 iPadOS 上,您可以定义多个场景并使用OpenWindowAction操作来激活它们。

Developer:

多谢Jeff!

关于SwiftUI的第一部分就到这里啦,后续会跟进整理第二部分和第三部分,敬请期待!⏳