为什么swift view不使用UIKit更新



我有带动画的swiftUI选项卡,还有UITabbarViewController,它包含这个swiftUI视图。

SwiftUI

struct MainTabBarView: View {

@ObservedObject var viewModel: MainTabBarViewModel

var body: some View {
VStack {
HStack(spacing: 0) {
TabItem(currentIndex: $viewModel.index, tabIndex: 0, tab: .home)
Spacer()
TabItem(currentIndex: $viewModel.index, tabIndex: 1, tab: .search)
Spacer()
TabItem(currentIndex: $viewModel.index, tabIndex: 2, tab: .library)
}.padding(.top, 8).padding(.leading, 28).padding(.trailing, 28)
.padding(.bottom, 8)
.frame(width: UIScreen.main.bounds.width)
.animation(.easeIn(duration: 0.2))
}

UITabbarViewController:

final class MainTabBarViewController: UITabBarController, Navigatable {
private var viewModel = MainTabBarViewModel()
// MARK: - Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
bindViewModel()
}

override func viewDidLoad() {
super.viewDidLoad()
configTabBarView()
}


private func configTabBarView() {
let view = UIHostingController(rootView: MainTabBarView(viewModel: viewModel))
addChild(child)
tabBar.addSubview(view.view)
view.didMove(toParent: self)
tabBar.setValue(true, forKey: "hidesShadow")
view.view.snp.makeConstraints { make in
make.leading.trailing.top.equalToSuperview()
make.height.equalTo(100)
}

}

ViewModel:

final class MainTabBarViewModel: NSObject, ObservableObject {

@Published var index: Int = 0 
}

这是我的带有选项卡的自定义视图的代码。当我按下选项卡时->视图中的索引此视图中的模型正在更改,然后

struct TabItem: View {

@Binding var currentIndex: Int
var tabIndex: Int
var isCurrentTab: Bool {
return currentIndex == tabIndex
}

var tab: Tabs

var body: some View {
HStack {
Image(uiImage: tab.icon).resizable().frame(width: 25, height: 25, alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/)
.foregroundColor(isCurrentTab ? R.color.primaryColor()!.swiftUI : R.color.grayScaleDark()!.swiftUI)
Text(isCurrentTab ? tab.title : "").font(Font(R.font.poppinsRegular(size: 16)! as CTFont))
.foregroundColor(isCurrentTab ? R.color.primaryColor()!.swiftUI : R.color.grayScaleDark()!.swiftUI)
}.padding(15)
.onTapGesture {
self.currentIndex = tabIndex
logWarn(String(tabIndex))
}
.background(self.tabIndex == currentIndex ? Color(R.color.pink()!) : Color.white)
.frame(height: 44.0)
.cornerRadius(22.0)
.clipped()
}

}

索引正在更改,但选项卡不更新视图的问题。它看起来像是视图不更新。

尽管编译给定的代码会很有帮助,但我认为我已经拼凑出了一个解决方案,允许当前索引保留在MainTabBarViewModel中,前提是它打算在未来保存其他内容。我还假设TabItem应该是足够通用的,不必特别依赖于MainTabVarViewModel

我的想法是基于在创建TabItem时提供当前索引的关键路径。如果不是因为TabItem更新了当前索引,这就足够简单了。然而,因为它确实更新了它,所以在onTapGesture闭包中,编译器抱怨它不能通过KeyPath进行写入,因为self是不可变的。所以…召唤鬼魂大卫·惠勒,我试着通过TabItem.init中保存的闭包来完成。。。它不存在,所以添加它是解决方案的一部分。

第一个TabItem成为通用:

struct TabItem<TabBarViewModel: ObservableObject>: View {
@ObservedObject var viewModel: TabBarViewModel
let indexKeyPath: WritableKeyPath<TabBarViewModel, Int>
let tapClosure: (Int) -> Void
// @Binding var currentIndex: Int
var currentIndex: Int { viewModel[keyPath: indexKeyPath] }
...
init(currentIndexIn viewModel: TabBarViewModel, at indexKeyPath: WritableKeyPath<TabBarViewModel, Int>, tabIndex: Int, tab: Tabs)
{
self.viewModel = viewModel
self.indexKeyPath = indexKeyPath
self.tabIndex = tabIndex
self.tab = tab
self.tapClosure = { self.viewModel[keyPath: indexKeyPath] = $0 }
}

这样,除了body中的这个位之外,TabItem中的所有内容都可以编译(在删除对未经验证代码的引用之后(

.onTapGesture {
currentIndex = tabIndex
print(String(tabIndex))
}

我将其更改为使用在init:中保存的闭包

.onTapGesture {
tapClosure(tabIndex)
print(String(tabIndex))
}

然后在MainTabBarViewbody中创建TabItem更改为:

TabItem(currentIndex: $viewModel.index, tabIndex: 0, tab: .home)

这个

TabItem(currentIndexIn: viewModel, at: .index, tabIndex: 0, tab: .home)

由于缺少太多代码,我无法编译和测试它,所以这有点像猜测。我删掉了缺失的代码,只是为了消除错误,所以我可以说,至少这个解决方案可以编译。它需要在实际应用程序中进行应用和测试,以验证它是否有效。

无论如何,假设它确实有效,这个解决方案仍然允许将索引保留在可观察对象中,而不依赖于该对象的特定类型。

最新更新