gpt4 book ai didi

swift - 如何实现一个自定义属性包装器,它将发布 SwiftUI 的更改以重新呈现它的 View

转载 作者:行者123 更新时间:2023-12-03 16:37:19 25 4
gpt4 key购买 nike

尝试实现一个自定义属性包装器,它也会以相同的方式发布其更改@Publish做。
例如。允许我的 SwiftUI 使用我的自定义包装器接收我的属性的更改。

我拥有的工作代码:

import SwiftUI

@propertyWrapper
struct MyWrapper<Value> {
var value: Value

init(wrappedValue: Value) { value = wrappedValue }

var wrappedValue: Value {
get { value }
set { value = newValue }
}
}

class MySettings: ObservableObject {
@MyWrapper
public var interval: Double = 50 {
willSet { objectWillChange.send() }
}
}

struct MyView: View {
@EnvironmentObject var settings: MySettings

var body: some View {
VStack() {
Text("\(settings.interval, specifier: "%.0f")").font(.title)
Slider(value: $settings.interval, in: 0...100, step: 10)
}
}
}

struct MyView_Previews: PreviewProvider {
static var previews: some View {
MyView().environmentObject(MySettings())
}
}

但是,我不喜欢调用 objectWillChange.send()对于 MySettings 中的每个属性类(class)。
@Published包装器效果很好,所以我尝试将它作为 @MyWrapper 的一部分来实现,但我没有成功。

我发现的一个很好的灵感是 https://github.com/broadwaylamb/OpenCombine ,但即使尝试使用那里的代码,我也失败了。

在为实现而苦苦挣扎时,
我意识到为了得到 @MyWrapper工作我需要准确理解 @EnvironmentObject@ObservedObject订阅 @Published 的更改.

任何帮助,将不胜感激。

最佳答案

直到 https://github.com/apple/swift-evolution/blob/master/proposals/0258-property-wrappers.md#referencing-the-enclosing-self-in-a-wrapper-type得到实现,我想出了下面的解决方案。
一般来说,我通过objectWillChange MySettings 的引用资料所有带有 @MyWrapper 注释的属性使用反射。

import Cocoa
import Combine
import SwiftUI

protocol PublishedWrapper: class {
var objectWillChange: ObservableObjectPublisher? { get set }
}

@propertyWrapper
class MyWrapper<Value>: PublishedWrapper {
var value: Value
weak var objectWillChange: ObservableObjectPublisher?

init(wrappedValue: Value) { value = wrappedValue }

var wrappedValue: Value {
get { value }
set {
value = newValue
objectWillChange?.send()
}
}
}

class MySettings: ObservableObject {
@MyWrapper
public var interval1: Double = 10

@MyWrapper
public var interval2: Double = 20

/// Pass our `ObservableObjectPublisher` to the property wrappers so that they can announce changes
init() {
let mirror = Mirror(reflecting: self)
mirror.children.forEach { child in
if let observedProperty = child.value as? PublishedWrapper {
observedProperty.objectWillChange = self.objectWillChange
}
}
}
}

struct MyView: View {
@EnvironmentObject
private var settings: MySettings

var body: some View {
VStack() {
Text("\(settings.interval1, specifier: "%.0f")").font(.title)
Slider(value: $settings.interval1, in: 0...100, step: 10)

Text("\(settings.interval2, specifier: "%.0f")").font(.title)
Slider(value: $settings.interval2, in: 0...100, step: 10)
}
}
}

struct MyView_Previews: PreviewProvider {
static var previews: some View {
MyView().environmentObject(MySettings())
}
}

关于swift - 如何实现一个自定义属性包装器,它将发布 SwiftUI 的更改以重新呈现它的 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59912443/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com