#swift #swiftui
#swift #swiftui
Вопрос:
Я пытаюсь внедрить UIView из SpritzSwift в приложение SwiftUI, но после первого рендеринга я не могу его обновить. Менеджер, который управляет UIView, работает, но сам UIView не обновляется. Я ожидал, что либо UIView.setNeedsDisplay() внутри контроллера представления, либо изменения в переменных @Bindable внутри оболочки вызовут updateUIView, но без кубиков.
Независимо от того, какие изменения я вношу в UIView или в его оболочку, он никогда не обновляется (например, фон никогда не обновляется до чистого цвета в примере кода). Как мне обновить это представление?
Вот код SwiftUI:
import SwiftUI
struct Content: View {
@State public var ssManager:SpritzSwiftManager = SpritzSwiftManager(withText: "", andWordPerMinute: Int(200))
@State public var ssView:SpritzSwiftView = SpritzSwiftView(frame: CGRect(x: 0, y: 0, width: 200, height: 600 ))
@State private var currentWord = ""
var body: some View {
VStack {
Text("SpritzTest")
.padding()
let spritzUIView = SpritzUIViewRepresentable(SpritzView: $ssView,SpritzViewManager:$ssManager, CurrentWord: $currentWord)
spritzUIView.padding()
Button(action:
{
ssManager = SpritzSwiftManager(withText: "Text try one two three", andWordPerMinute: 200)
spritzUIView.SpritzView = SpritzSwiftView(frame: CGRect(x: 0, y: 0, width: 200, height: 40 ))
spritzUIView.SpritzView.backgroundColor = .clear
ssManager.startReading { (word, finished) in
if !finished {
self.ssView.updateWord(word!)
currentWord = word!.word
spritzUIView.CurrentWord = currentWord
}
}
})
{
Text("Start")
}
}
}
}
и вот оболочка:
struct SpritzUIViewRepresentable : UIViewRepresentable{
@Binding var SpritzView:SpritzSwiftView
@Binding var SpritzViewManager:SpritzSwiftManager
@Binding var CurrentWord:String
func makeUIView(context: Context) -> SpritzSwiftView {
return SpritzView
}
func updateUIView(_ uiView: SpritzSwiftView, context: Context) {
}
}
Ответ №1:
Вам нужно создать представление UIKit внутри makeUIView
и через привязку передавать только зависимые данные. Это изменение привязки при изменении связанного состояния — источника истины — updateUIView
вызывает вызовы , в которых вы должны обновить свое представление UIKit.
Здесь приведен только упрощенный демонстрационный эскиз, чтобы показать концепцию (могут быть опечатки):
struct SpritzUIViewRepresentable : UIViewRepresentable{
@Binding var currentWord: SpritzSwiftWord
@Binding var backgroundColor: UIColor
func makeUIView(context: Context) -> SpritzSwiftView {
// create and configure view here
return SpritzSwiftView(frame: CGRect.zero) // frame does not matter here
}
func updateUIView(_ uiView: SpritzSwiftView, context: Context) {
// update view properties here from bound external data
uiView.backgroundColor = backgroundColor
uiView.updateWord(currentWord)
}
}
и кнопка теперь должна просто изменить данные модели
VStack {
Text("SpritzTest")
.padding()
SpritzUIViewRepresentable(backgroundColor: $backgroundColor, SpritzViewManager:$ssManager, currentWord: $currentWord)
.padding()
Button(action:
{
ssManager = SpritzSwiftManager(withText: "Text try one two three", andWordPerMinute: 200)
self.backgroundColor = .clear
ssManager.startReading { (word, finished) in
if !finished {
self.currentWord = word
}
}
})
{
Text("Start")
}
предполагая обновленные свойства
@State private var currentWord = SpritzSwiftWord(word: "")
@State private var backgroundColor = UIColor.white // whatever you want
Комментарии:
1. Идеально! Это прекрасно работает. Теперь я лучше понимаю, как это работает. Из документации совсем не ясно, что updateUIView должен содержать связанные данные, я надеюсь, что этот ответ поможет кому-нибудь в будущем.