将工具栏重构为另一个文件
Refactoring out a toolbar to another file
经验丰富的 Swift UI 套件编码器,但绝对不会使用 SwiftUI。假设我有以下代码:
HStack {
Button(
action: { self.createNode() },
label: {
Text("ADD").bold().font(.system(size: 40)).frame(width: 200, height: 80).background(Color.yellow).cornerRadius(5)
})
Spacer()
Button(
action: { self.deleteNode() },
label: {
Text("DELETE").bold().font(.system(size: 40)).frame(width: 200, height: 80).background(Color.yellow).cornerRadius(5)
})
}
一个非常简单的工具栏。但是现在,让我们再添加 (a) 四个 Buttons
并将其放入 "root" 视图中。在 UIKit 中我们称之为 大型视图控制器。
我正在尝试将整个 HStack
移出根视图,但 action
出现问题。我知道我可以创建 ViewModifiers
、自定义视图,并且 - 至少在某种程度上 - 将一些东西移动到扩展中。但是我无法将此扩展 "lock, stock, and barrel" 移动到其他任何地方。我一直在尝试将 createNode()
和 deleteNode()
移动到其他任何地方。
我确定是我在尝试将方钉 (UIKit
) 装入圆孔 (SwiftUI
),但是 none WWDC 会议或其他资源我我发现似乎在为我指明正确的方向。我错过了什么?
编辑:
以下是这两个操作 - 它们工作正常。
@State var nodes: [Node] = []
func createNode() {
let newNodeName = nodes.count + 1
let newNode = Node(name: newNodeName)
nodes.append(newNode)
}
func deleteNode() {
if nodes.count != 0 {
nodes.remove(at: nodes.count - 1)
}
}
我的问题不是关于Swift,也不是关于维护数组。它是关于 SwiftUI,以及如何 "refactor" 我当前的 140 行文件变成更小的东西 - 在这种情况下通过删除 "top bar" HStack 到它自己的文件 Xcode.
这个水平堆叠的按钮最终将编号为 5(它是一个 iPad 唯一的应用程序),我的问题是如何移动按钮 "actions",正确键入 () -> Void
。
更多,这是整个文件的简化视图(请原谅使用降价,我找不到更好的方式来表示它):
HStack
VStack
HStack <-- Contains the Buttons that add/delete the nodes
HStack
HStack <-- Contains the nodes themselves, will soon contain thumbnails
List
如果我的 HStack 由 Text
视图的水平行组成,它工作正常。但是当我尝试将 Button
(无论是嵌套在 HStack 中还是独立的)移动到一个单独的文件中时,我遇到了构建问题。
我建议将操作和 @State
重构到视图模型中。
final class ViewModel: BindableObject {
let didChange = PassthroughSubject<Void, Never>()
var nodes: [Node] = [] {
didSet {
didChange.send(())
}
}
func createNode() {
let newNodeName = nodes.count + 1
let newNode = Node(name: newNodeName)
nodes.append(newNode)
}
func deleteNode() {
if nodes.count != 0 {
nodes.remove(at: nodes.count - 1)
}
}
}
所有需要访问动作的视图,需要声明这个属性:
@EnvironmentObject var viewModel: ViewModel
有关 @EnvironmentObject
here 的更多信息。
每当节点发生变化时,所有声明环境对象的子视图都将被重绘。
你只需要在容器视图中设置环境对象,它就会被传递给所有的子视图。
例如
ContentView().environmentObject(ViewModel())
您的视图层次结构:
HStack
VStack
HStack <- @EnvironmentObject (will call the actions)
HStack
HStack <- @EnvironmentObject (will use viewModel.nodes to display nodes)
List
经验丰富的 Swift UI 套件编码器,但绝对不会使用 SwiftUI。假设我有以下代码:
HStack {
Button(
action: { self.createNode() },
label: {
Text("ADD").bold().font(.system(size: 40)).frame(width: 200, height: 80).background(Color.yellow).cornerRadius(5)
})
Spacer()
Button(
action: { self.deleteNode() },
label: {
Text("DELETE").bold().font(.system(size: 40)).frame(width: 200, height: 80).background(Color.yellow).cornerRadius(5)
})
}
一个非常简单的工具栏。但是现在,让我们再添加 (a) 四个 Buttons
并将其放入 "root" 视图中。在 UIKit 中我们称之为 大型视图控制器。
我正在尝试将整个 HStack
移出根视图,但 action
出现问题。我知道我可以创建 ViewModifiers
、自定义视图,并且 - 至少在某种程度上 - 将一些东西移动到扩展中。但是我无法将此扩展 "lock, stock, and barrel" 移动到其他任何地方。我一直在尝试将 createNode()
和 deleteNode()
移动到其他任何地方。
我确定是我在尝试将方钉 (UIKit
) 装入圆孔 (SwiftUI
),但是 none WWDC 会议或其他资源我我发现似乎在为我指明正确的方向。我错过了什么?
编辑:
以下是这两个操作 - 它们工作正常。
@State var nodes: [Node] = []
func createNode() {
let newNodeName = nodes.count + 1
let newNode = Node(name: newNodeName)
nodes.append(newNode)
}
func deleteNode() {
if nodes.count != 0 {
nodes.remove(at: nodes.count - 1)
}
}
我的问题不是关于Swift,也不是关于维护数组。它是关于 SwiftUI,以及如何 "refactor" 我当前的 140 行文件变成更小的东西 - 在这种情况下通过删除 "top bar" HStack 到它自己的文件 Xcode.
这个水平堆叠的按钮最终将编号为 5(它是一个 iPad 唯一的应用程序),我的问题是如何移动按钮 "actions",正确键入 () -> Void
。
更多,这是整个文件的简化视图(请原谅使用降价,我找不到更好的方式来表示它):
HStack
VStack
HStack <-- Contains the Buttons that add/delete the nodes
HStack
HStack <-- Contains the nodes themselves, will soon contain thumbnails
List
如果我的 HStack 由 Text
视图的水平行组成,它工作正常。但是当我尝试将 Button
(无论是嵌套在 HStack 中还是独立的)移动到一个单独的文件中时,我遇到了构建问题。
我建议将操作和 @State
重构到视图模型中。
final class ViewModel: BindableObject {
let didChange = PassthroughSubject<Void, Never>()
var nodes: [Node] = [] {
didSet {
didChange.send(())
}
}
func createNode() {
let newNodeName = nodes.count + 1
let newNode = Node(name: newNodeName)
nodes.append(newNode)
}
func deleteNode() {
if nodes.count != 0 {
nodes.remove(at: nodes.count - 1)
}
}
}
所有需要访问动作的视图,需要声明这个属性:
@EnvironmentObject var viewModel: ViewModel
有关 @EnvironmentObject
here 的更多信息。
每当节点发生变化时,所有声明环境对象的子视图都将被重绘。
你只需要在容器视图中设置环境对象,它就会被传递给所有的子视图。
例如
ContentView().environmentObject(ViewModel())
您的视图层次结构:
HStack
VStack
HStack <- @EnvironmentObject (will call the actions)
HStack
HStack <- @EnvironmentObject (will use viewModel.nodes to display nodes)
List