我有一个基本的视图控制器子类,它包含一个UIStackView和一个UIButton。我想运行一些代码,每次从堆栈视图的arrangedSubviews
数组使用组合添加或删除视图。这是我失败的尝试:
import Combine
import UIKit
class ViewController: UIViewController {
@IBOutlet var stackView: UIStackView!
@IBOutlet var button: UIButton!
var cancelables = Set<AnyCancellable>()
override func viewDidLoad() {
super.viewDidLoad()
stackView.publisher(for: .arrangedSubviews).sink { views in
button.isEnabled = views.count < 5
}
.store(in: &cancelables)
}
@IBAction func addTapped(_ sender: UIButton) {
let customView = CustomView()
stackView.addArrangedSubview(customView)
}
}
每次我点击按钮,一个新的视图被添加到堆栈视图,但对arrangedSubviews
的更改没有发布,这不会触发sink
块中的代码。在上述情况下,即使arrangedSubviews.count
大于5,按钮仍然启用。
我如何解决这个问题,以便我可以正确地发布更改每当一个新的视图被添加或从arrangedSubviews
数组删除?
谢谢你的帮助。
感谢Fabio Felici的评论,我猜UIStackView.arrangedSubviews
不是kvo兼容的,这一定是导致我的尝试不工作的原因。
我设法以不同的方式处理这个问题,通过子类化UIStackView
并添加Published
计数器,该计数器包含每次调用插入和删除函数时arrangedSubviews.count
的更新值。
class CountReactableStackView: UIStackView {
@Published var numberOfArrangedSubviews = 0
override func addArrangedSubview(_ view: UIView) {
super.addArrangedSubview(view)
numberOfArrangedSubviews = arrangedSubviews.count
}
override func removeArrangedSubview(_ view: UIView) {
super.removeArrangedSubview(view)
numberOfArrangedSubviews = arrangedSubviews.count
}
override func insertArrangedSubview(_ view: UIView, at stackIndex: Int) {
super.insertArrangedSubview(view, at: stackIndex)
numberOfArrangedSubviews = arrangedSubviews.count
}
}
然后订阅并响应numberOfArrangedSubviews
。
由于arrangedSubviews
是只读的,只能通过上述函数更改,这个简单的解决方案回答了我的问题。我仍然很好奇是否有一种方法可以直接观察和响应arrangedSubviews
的插入和删除。