swift - 我需要刷新 SwiftUI 视图,当 @propertyWrapper 被传递到
问题描述
我有一个示例结构:
public struct Axis: Hashable, CustomStringConvertible {
public var name: String
public var description: String {
return "Axis: \"\(name)\""
}
}
和属性包装器对[Axis]
结构进行一些操作。
@propertyWrapper
struct WrappedAxes {
var wrappedValue: [Axis] {
// This is just example, in real world it's much more complicated.
didSet {
for index in wrappedValue.indices {
var elems = Array(wrappedValue[index].name.split(separator: " "))
if elems.count>1 {
elems.removeLast()
}
let new = elems.reduce(into:"", {$0 += "\($1) "})
wrappedValue[index].name = new+("\(Date())")
} } } }
我尝试Axes
在 SwiftUI 视图中添加、插入和删除:
public struct ContentView: View {
@Binding var axes: [Axis]
public var body: some View {
VStack {
ForEach(axes.indices, id:\.self) {index in
HStack {
TextField("", text: $axes[index].name)
Button("Delete", action: {deleteAxis(index)})
Button("Insert", action: {insertAxis(index)})
}
}
Button("Add", action: addAxis)
}
}
var addAxis: () -> Void {
return {
axes.append(Axis(name: "New"))
print (axes)
}
}
var deleteAxis: (_:Int)->Void {
return {
if $0 < axes.count {
axes.remove(at: $0)
}
print (axes)
}
}
var insertAxis: (_:Int)->Void {
return {
if $0 < axes.count {
axes.insert(Axis(name: "Inserted"), at: $0)
}
print (axes)
}
}
public init (axes: Binding<[Axis]>) {
self._axes = axes
}
}
就print (axes)
显示所做的更改而言,视图永远不会更新。我制作了非常小的应用程序进行测试,我在其中调用ContentView
:
class AppDelegate: NSObject, NSApplicationDelegate {
var window: NSWindow!
@WrappedAxes var axes = [Axis(name: "FirstOne")]
func applicationDidFinishLaunching(_ aNotification: Notification) {
let contentView = ContentView(
axes: Binding (
get: {self.axes},
set: { [self] in axes = $0}))
.... // No fancy stuff
我对代码本身的所有批评持开放态度,并提供帮助:如何在更改时推动此视图(以及所有可能的未来子视图)进行更新axes
?
解决方案
问题是@Binding 用于嵌套视图。当您想在 SwiftUI 视图中进行更改时,您必须在操作开始的地方使用 @State。另外,您不需要以这种方式设置初始化程序。您可以像这样在 ObservableObject 中设置您的值来处理您的逻辑:
struct Axis {
var name: String
var description: String {
return "Axis: \"\(name)\""
}
}
final class AxisViewModel: ObservableObject {
@Published var axes: [Axis] = [Axis(name: "First")]
init() { handleAxes() }
func addAxis() {
axes.append(Axis(name: "New"))
handleAxes()
}
func insertAxis(at index: Int) {
axes.insert(Axis(name: "Inserted"), at: index)
handleAxes()
}
func handleAxes() {
for index in axes.indices {
var elems = Array(axes[index].name.split(separator: " "))
if elems.count > 1 {
elems.removeLast()
}
let new = elems.reduce(into:"", { $0 += "\($1) " })
axes[index].name = new + ("\(Date())")
}
}
}
struct ContentView: View {
@ObservedObject var viewModel = AxisViewModel()
var body: some View {
VStack {
ForEach(viewModel.axes.indices, id:\.self) { index in
HStack {
TextField("", text: $viewModel.axes[index].name)
Button("Insert", action: { viewModel.insertAxis(at: index) })
}
}
Button("Add", action: viewModel.addAxis)
}
}
}
推荐阅读
- url - Vuetify 标准设置(babel/eslint)图像加载失败
- r - 计算 R 中每一行的持续时间到特定百分比变化
- python - Python 反向兼容 3.6 到 2.7
- java - 在 Spring 中将状态存储在控制器中
- postgresql - 为什么表中的不同数据可以以不同的性能进行处理?
- python - 使用命令自动加载多个 Unix 屏幕
- javascript - 如何链接javascript选择器
- bluetooth-lowenergy - 当外围特征值改变时 Central 不通知
- python - 考虑 pandas DataFrame 的 drop_duplicates 方法中的重复索引
- ckeditor - 如何在 TYPO3 8.7 中启用 rte_ckeditor 中的 SCAYT