- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在测试 Combine 框架并使用 BindableObject 作为通知中心,以便在 SwiftUI ContentView 的多个 View 之间传递数据。
其中一个 View 是一个表。我单击一行,在打印检查点中检测到该值,因此可绑定(bind)对象收到更新。
问题是,新字符串没有广播到 ContentView 的接收端。
我是新手。
带有 TableView 的 View Controller .swift(广播器):
import SwiftUI
import Combine
final public class NewestString: BindableObject {
public var didChange = PassthroughSubject<NewestString, Never>()
var newstring: String {
didSet {
didChange.send(self)
print("Newstring: \(newstring)") //<-- Change detected
}
}
init(newstring: String) {
self.newstring = newstring
}
public func update() {
didChange.send(self)
print("--Newstring: \(newstring)")
}
}
final class AViewController: UIViewController {
@IBOutlet weak var someTableView: UITableView!
var returnData = NewestString(newstring:"--")
override func viewDidLoad() {
super.viewDidLoad()
}
}
/// [.....] More extensions here
extension AViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let completion = someResults[indexPath.row]
//// [......] More code here
self.returnData.newstring = "Test string" //<--- change caused
}
}
}
主要内容 View (广播目的地):
import SwiftUI
import Combine
struct PrimaryButton: View {
var title: String = "DefaultTitle"
var body: some View {
Button(action: { print("tapped") }) {
Text(title)
}
}
}
struct MyMiniView: View {
@State var aTitle: String = "InitialView"
var body: some View {
VStack{
PrimaryButton(title: aTitle)
}
}
}
struct ContentView: View {
@State private var selection = 0
@ObjectBinding var desiredString: NewestString = NewestString(newstring: "Elegir destino") // <-- Expected receiver
var body: some View {
TabbedView(selection: $selection){
ZStack() {
MyMiniView(aTitle: self.desiredString.newstring ?? "--")
// expected end use of the change, that never happens
[...]
}
struct AView: UIViewControllerRepresentable {
typealias UIViewControllerType = AViewController
func makeUIViewController(context: UIViewControllerRepresentableContext<AView>) -> AViewController {
return UIStoryboard(name: "MyStoryboard", bundle: nil).instantiateViewController(identifier: String(describing: AViewController.self)) as! AViewController
}
func updateUIViewController(_ uiViewController: AViewController, context: UIViewControllerRepresentableContext<AView>) {
//
}
它编译、运行并打印更改,但 MyMiniView 的 PrimaryButton 没有更新。
最佳答案
我找不到您在哪里使用 AViewController
的实例,但问题是您正在使用可绑定(bind)对象 NewestString
的多个实例。
ContentView
作为NewestString
的实例,每次更新都会触发 View 重新加载。
struct ContentView: View {
@State private var selection = 0
// First instance is here
@ObjectBinding var desiredString: NewestString = NewestString(newstring: "Elegir destino") // <-- Expected receiver
}
NewestString
的第二个实例在您实际修改的 AViewController
中。但是,由于它不是 NewestString
的同一个实例(实际在内容 View 中声明的实例),修改它不会触发 View 重新加载。
final class AViewController: UIViewController {
@IBOutlet weak var someTableView: UITableView!
// The second instance is here
var returnData = NewestString(newstring:"--")
}
要解决这个问题,您需要找到一种方法将在您的 ContentView
中创建的 NewestString
实例“转发”到 View Controller 。
ObjectBinding
的实例传递给 View Controller 的方法:当您使用 SwiftUI 将 View 添加到层次结构中时,您需要传递一个 Binding
值,您希望从 View Controller 访问该值:
struct ContentView: View {
@ObjectBinding var desiredString = NewestString(newstring: "Hello")
var body: some View {
VStack {
AView(binding: desiredString[\.newstring])
Text(desiredString.newstring)
}
}
}
The
subscript
with a key path will produce aBinding
of the given property:protocol BindableObject {
subscript<T>(keyPath: ReferenceWritableKeyPath<Self, T>) -> > Binding<T> { get }
}
在 View Controller 包装器 (UIViewControllerRepresentable
) 中,您需要将给定的 Binding
转发给实际的 View Controller 实例。
struct AView: UIViewControllerRepresentable {
typealias UIViewControllerType = AViewController
var binding: Binding<String>
func makeUIViewController(context: UIViewControllerRepresentableContext<AView>) -> AViewController {
let controller = AViewController()
controller.stringBinding = binding // forward the binding object
return controller
}
func updateUIViewController(_ uiViewController: AViewController, context: UIViewControllerRepresentableContext<AView>) {
}
}
然后,在您的 View Controller 中,您可以使用绑定(bind)来更新您的值(使用 .value
属性):
final class AViewController: UIViewController {
var stringBinding: Binding<String>!
override func viewDidLoad() {
super.viewDidLoad()
stringBinding.value = "Hello world !!"
}
}
当调用 View Controller 的viewDidLoad
时,desiredString
(在ContentView
中)将被更新为“Hello world!!”,只是就像显示的文本 (Text(desiredString.newstring)
)。
关于SwiftUI ObjectBinding 不会使用 combine 从可绑定(bind)对象接收 didchange 更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57054916/
SwiftUI 具有 .animate() 的隐式动画,以及使用 .withAnimation() 的显式.但是,我不知道如何为图像更改设置动画: struct ImageViewWidget : V
我有一个 SwiftUI View ,它有一个 @ObjectBinding progression: Progressable 像这样: struct ProgressBarComponent :
当我们有 @Binding 属性包装器时,@EnvironmentObject 的目的是什么?我无法弄清楚为什么需要@EnvironmentObject。我查看了这些帖子,但它并不是我想要的 Envi
我想删除一个标记为 @ObjectBinding 的对象,例如为了清理一些 TextFields。 我试图将对象引用设置为 nil,但没有成功。 import SwiftUI import Combi
我正在尝试学习Combine,它对我来说是一个PITA。我从未学过 RX Swift,所以这对我来说是全新的。我确信我错过了一些简单的事情,但希望得到一些帮助。 我正在尝试从 API 获取一些 JSO
我正在尝试在 SwiftUI 中设置一个基本列表,但我遇到了一个对我来说意义不大的编译时错误。这是错误: Cannot convert value of type 'Text' to closure
我有一个简单的 bean,它有一些相互关联的属性。例如,这个 bean 有一个名为 discountRate 的属性和另一个名为 discountValue 的属性。 discountRate 是应用
在 SwiftUI 中,您可以将 Publisher 的实例直接用作 @ObjectBinding 属性,还是必须将其包装在实现 BindableObject 的类中? let subject = P
我正在测试 Combine 框架并使用 BindableObject 作为通知中心,以便在 SwiftUI ContentView 的多个 View 之间传递数据。 其中一个 View 是一个表。我单
我是一名优秀的程序员,十分优秀!