由于SwiftUI的限制,我通常需要跳回到UIKit并利用UIKit组件。一切都很好,但是我发现我通常需要继续创建单独的结构来容纳所需的功能。
例如。假设我有一个包含4个字段的表单,例如名字,姓氏,电子邮件和密码。我通常需要为每个组件创建单独的UIViewRepresentable UIKit组件。
我目前在一个项目中,我有2个简单的滑块,可以在移动2个不同的标签时更新它们。在SwiftUI中重用相同的UIViewRepresentable UISlider组件会将两个滑块视为1,因为它们都引用相同的视图模型属性,因此我需要创建单独的组件而不是重复使用它们。
我想我还是想看看是否有一种更有效的方法来执行此操作,因为我已经重复了一段时间了,所以除了诸如哪种键盘之类的代码外,代码之间通常没有太大区别显示,颜色等
下面是我如何从SwiftUI进入UIKit的示例。我正在创建一个屏幕,该屏幕允许使用滑块选择下注赔率和赌注。
我跟踪何时更改滑块的值,并将该值存储在我的视图模型中的@Published var中。
self.bViewModel.odds
我通过使用滑块的视图中的环境变量访问此视图模型,并使用它来更新文本标签。
VStack {
HStack(spacing: 0) {
Text("\(self.bViewModel.odds)")
.font(Font.system(size: 15, weight: .semibold, design: .default))
.foregroundColor(Color("CustomPurple"))
.frame(minHeight: 0)
.padding(.top, 3)
.padding(.bottom, 3)
Spacer()
}
SliderView()
.frame(minHeight: 25, maxHeight: 25)
}
.padding(.bottom, 30)
SliderView结构看起来像这样:
struct SliderView: UIViewRepresentable {
final class Coordinator: NSObject {
@EnvironmentObject var bViewModel: BViewModel
init(bViewModel: EnvironmentObject<BViewModel>)
{
self._bViewModel = bViewModel
}
// Create a valueChanged(_:) action
@objc func valueChanged(_ sender: UISlider) {
self.bViewModel.odds = Double(sender.value)
}
}
func makeCoordinator() -> SliderView.Coordinator {
Coordinator(bViewModel: self._bViewModel)
}
@EnvironmentObject var bViewModel: BViewModel
func makeUIView(context: Context) -> UISlider {
let slider = UISlider(frame: .zero)
slider.minimumValue = 0.00
slider.maximumValue = 100.00
slider.addTarget(
context.coordinator,
action: #selector(Coordinator.valueChanged(_:)),
for: .valueChanged
)
return slider
}
func updateUIView(_ uiView: UISlider, context: Context) {
}
}
现在,我需要一个用于选择桩的滑块,但是如果不编写大量代码使其无法将其视为其他滑块,则无法从上方重用同一滑块。复制代码并更改我访问视图模型的odds变量的行更加容易,以便它可以访问takes变量,例如
@objc func valueChanged(_ sender: UISlider) {
self.bViewModel.stake = Double(sender.value)
}
这是我工作了几个月的方法,但一直感觉不对。但是,我似乎无法想到另一种方法来解决此问题。
有什么建议?您通常如何处理这种情况?
提前致谢。
新答案,现在带有EnvironmentObject
import SwiftUI
import Combine
class ViewModel : ObservableObject {
@Published var sliderValue1 : Double = 3.14
@Published var sliderValue2 : Double = 42.0
@Published var sliderValue3 : Double = 3.14
@Published var sliderValue4 : Double = 42.0
}
struct SliderView: UIViewRepresentable {
@Binding var value : Double
class Coordinator: NSObject {
var sliderView: SliderView
init(_ sliderView: SliderView) {
self.sliderView = sliderView
}
@objc func valueChanged(_ slider: UISlider) {
sliderView.value = Double(slider.value)
}
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIView(context: Context) -> UISlider {
let slider = UISlider(frame: .zero)
slider.minimumValue = 0.00
slider.maximumValue = 100.00
slider.addTarget(
context.coordinator,
action: #selector(Coordinator.valueChanged(_:)),
for: .valueChanged
)
return slider
}
func updateUIView(_ uiView: UISlider, context: Context) {
}
}
struct ContentView : View {
@EnvironmentObject var viewModel : ViewModel
var body: some View {
VStack {
Text("\(self.viewModel.sliderValue1)")
Slider(value: Binding<Double>(get:
{ return self.viewModel.sliderValue1 },
set: {
print($0)
self.viewModel.sliderValue1 = $0
}))
Text("\(self.viewModel.sliderValue2)")
Slider(value: Binding<Double>(get:
{ return self.viewModel.sliderValue2 },
set: {
print($0)
self.viewModel.sliderValue2 = $0
}))
Text("\(viewModel.sliderValue3)")
SliderView(value: Binding<Double>(get:
{ return self.viewModel.sliderValue3 },
set: {
print($0)
self.viewModel.sliderValue3 = $0
}))
Text("\(viewModel.sliderValue4)")
SliderView(value: Binding<Double>(get:
{ return self.viewModel.sliderValue4 },
set: {
print($0)
self.viewModel.sliderValue4 = $0
}))
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
var value1 : Double = 0.4
var value2 : Double = 0.4
var value3 : Double = 0.4
var value4 : Double = 0.4
return ContentView().environmentObject(ViewModel())
}
}
好的,因为您是如此有礼貌,并且回答得很快,所以我尝试了一下,希望现在我得到了您需要的东西;)
我确实让“旧滑块”进入了,但是下面的两个滑块来自我的UIViewRepresentable。
新答案:
struct SliderView: UIViewRepresentable {
@Binding var value : Double
class Coordinator: NSObject {
var sliderView: SliderView
init(_ sliderView: SliderView) {
self.sliderView = sliderView
}
@objc func valueChanged(_ slider: UISlider) {
sliderView.value = Double(slider.value)
}
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIView(context: Context) -> UISlider {
let slider = UISlider(frame: .zero)
slider.minimumValue = 0.00
slider.maximumValue = 100.00
slider.addTarget(
context.coordinator,
action: #selector(Coordinator.valueChanged(_:)),
for: .valueChanged
)
return slider
}
func updateUIView(_ uiView: UISlider, context: Context) {
}
}
struct ContentView : View {
@State var sliderValue1 : Double
@State var sliderValue2 : Double
@State var sliderValue3 : Double
@State var sliderValue4 : Double
var body: some View {
VStack {
Text("\(sliderValue1)")
Slider(value: Binding<Double>(get:
{ return self.sliderValue1 },
set: {
print($0)
self.sliderValue1 = $0
}))
Text("\(sliderValue2)")
Slider(value: Binding<Double>(get:
{ return self.sliderValue2 },
set: {
print($0)
self.sliderValue2 = $0
}))
Text("\(sliderValue3)")
SliderView(value: Binding<Double>(get:
{ return self.sliderValue3 },
set: {
print($0)
self.sliderValue3 = $0
}))
Text("\(sliderValue4)")
SliderView(value: Binding<Double>(get:
{ return self.sliderValue4 },
set: {
print($0)
self.sliderValue4 = $0
}))
}
}
}
老答案:
好的,我想通了没有UIViewRepresentable的方法。
请参阅此示例。
您所要做的就是使用您的sliderVariables(sliderValue1或您喜欢的任何名称)扩展viewModel,然后
struct ContentView : View {
@State var sliderValue1 : Double
@State var sliderValue2 : Double
var body: some View {
VStack {
Text("\(sliderValue1)")
Slider(value: Binding<Double>(get:
{ return self.sliderValue1 },
set: {
print($0)
self.sliderValue1 = $0
}))
Text("\(sliderValue2)")
Slider(value: Binding<Double>(get:
{ return self.sliderValue2 },
set: {
print($0)
self.sliderValue2 = $0
}))
}
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句