How can I use the pressed key information in my SwiftUI? I try to use @EnvironmentObject to share key with my SwiftUI but i get every time crash in sendKeybKey: Thread 1: Fatal error: No ObservableObject of type UserData found. A View.environmentObject(_:) for UserData may be missing as an ancestor of this view. In .environmentObject is already used in SceneDelegate, but was is wrong? My Code:
class KeyTestController<Content>: UIHostingController<Content> where Content: View {
@EnvironmentObject var userData: UserData
override func becomeFirstResponder() -> Bool {
true
}
override var keyCommands: [UIKeyCommand]? {
var keys = [UIKeyCommand]()
for num in "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!\r" {
keys.append(
UIKeyCommand(
input:String(num),
modifierFlags: [],
action:
#selector(sendKeybKey)
)
)
}
return keys
}
@objc func sendKeybKey(_ sender: UIKeyCommand) {
userData.collectChar = sender.input ?? ""
print(">>> test was pressed \(sender.input ?? "")")
}
}
In SceneDelegate
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = KeyTestController/*UIHostingController*/(
rootView: myList()
.environmentObject(UserData())
)
self.window = window
window.makeKeyAndVisible()
}
and UserData:
final class UserData: ObservableObject {
@Published var datasetUIIdata: [DatasetUII] = []
@Published var collectChar : String = ""
@Published var collectText : String = ""
}
My SwiftUI View
struct myList: View {
@EnvironmentObject var userData: UserData
var body: some View {
VStack {
HStack {
Text("Key\(userData.collectChar)").font(.largeTitle)
}
.padding()
List {
ForEach(userData.datasetUIIdata, id: \.self) { (item) in
Text(item.userName)
}
.onDelete(perform: delete)
}
.padding()
}
}
func delete(at offsets: IndexSet) {
userData.datasetUIIdata.remove(atOffsets: offsets)
}
}
Anyone up for a quick help to a newbie?
Thanks!
Waldemar
You don't need @EnvironmentObject
in controller, UserData
is a reference type, so you can inject same object directly in view and in controller.
class KeyTestController<Content>: UIHostingController<Content> where Content: View {
var userData: UserData
so creation then will be as below
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
let userData = UserData()
let contentView = myList().environmentObject(userData) // in view !!
let controller = KeyTestController(rootView: contentView)
controller.userData = userData // in controller !!
window.rootViewController = controller