NSKeyValueCoding.setValue(_:forKey:) 在 SwiftUI 中不工作
NSKeyValueCoding.setValue(_:forKey:) not working in SwiftUI
我无法生成适当的最小工作示例,主要是由于我对 iOS 开发的新手水平理解,但我确实有一个简单的 SwiftUI 项目可能会有所帮助。
在我的 ContentView.swift:
import SwiftUI
struct ContentView: View {
@State var viewText :String
var myClass :MyClass
var body: some View {
VStack{
Text(viewText)
.padding()
Button("Update Text", action: {
myClass.update()
viewText = myClass.txt
})
}
}
}
class MyClass: NSObject {
var txt :String = ""
var useSetVal :Bool = false
func update(){
if(useSetVal){
setValue("used set val", forKey: "txt")
} else {
txt = "used ="
}
useSetVal = !useSetVal
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
let mc = MyClass()
ContentView(viewText: "", myClass: mc)
}
}
在我的 PracticeApp.swift
import SwiftUI
@main
struct PracticeApp: App {
var body: some Scene {
WindowGroup {
let mc = MyClass()
ContentView(viewText: "", myClass: mc)
}
}
}
在此应用程序中,我希望在按下按钮时看到文本在“used =”和“used setVal”之间切换。相反,当我调用 setValue:
时出现异常
Thread 1: "[<Practice.MyClass 0x60000259dc20> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key txt."
我一直在查看答案 here 但由于大多数答案都涉及 xib 和故事板文件(我没有,或者不知道如何找到),我不知道看看它们之间的关系。
顺便说一句,即使我实际尝试修复的应用程序不使用 SwiftUI 并且 setValue 的问题有所不同,但我确实没有 .xib 或 .storyboard 文件或我只是不知道在哪里可以找到它们。
如果有人可以帮助我找出我的示例中的问题,或者可以让我更接近解决实际应用程序的问题(包括如何生成适当的 MWE),我将不胜感激。
我相信我已经写的内容足以解决这个问题(至少一开始是这样),但对于那些感兴趣的人,我想我会添加完整的故事。
全文
我是 iOS 开发的新手,我刚刚获得了旧 iOS 应用程序的所有权。它自 2017 年以来就没有真正被触及过。我注意到一个动画不起作用。虽然我无法验证它是否曾经工作过,但我有充分的理由假设它曾经工作过,但我不能说它何时停止工作。
我注意到的一个问题是动画属性应该使用 NSKeyValueCoding.setValue(_:forKey:) 函数更新,但调用该函数时似乎没有任何反应。
我能够通过用我自己的 setValue 函数覆盖来解决这个问题,该函数基本上使用 switch 语句将每个键映射到其对应的值。但是,这并没有修复动画或解释为什么 setValue 函数不起作用。
因为 setValue 函数和 CABasicAnimation.add(_:forKey:) 都依赖于相同的 keyPath,我想知道解决一个问题是否可以帮助我解决另一个问题。我决定专注于 setValue 问题(至少现在)。
当我开始一个新项目作为 MWE 使用时,我注意到 Xcode 13.0 (13A233) 提供的 Storyboard 和 SwiftUI 界面选项都没有启动我的项目结构匹配我现有的项目。我很清楚 SwiftUI 是新的,与我现有的项目有很大不同,但 Storyboard 界面也不熟悉,在阅读教程几分钟后,我未能构建一个能够响应按钮按下的 Storyboard 应用程序(我发现的所有情节提要应用程序教程似乎都是为 Xcode) 的旧版本设置的。
SwiftUI 将要求您使用@ObservedObject 来对对象的变化做出反应。您可以使它符合观察对象和键值操作,如下所示:
struct ContentView: View {
@State var viewText :String
@ObservedObject var myClass :MyClass
var body: some View {
VStack{
Text(viewText)
.padding()
Button("Update Text", action: {
myClass.update()
viewText = myClass.txt
})
}
}
}
class MyClass: NSObject, ObservableObject {
@objc dynamic var txt: String = ""
@Published var useSetVal: Bool = false
func update(){
if(useSetVal){
setValue("used set val", forKey: "txt")
} else {
txt = "used ="
}
useSetVal = !useSetVal
}
}
您需要使 txt
属性 对 Objective-C 可用,以便使其与 KVO/KVC 一起使用。这是必需的,因为键值 Observing/Coding 机制是一项 Objective-C 功能。
所以,要么
class MyClass: NSObject {
@objc var txt: String = ""
,或
@objcMembers class MyClass: NSObject {
var txt: String = ""
这将修复该错误,并应使您的应用按预期运行。但是,正如其他人所说,您需要对代码进行更多更改才能遵守 SwiftUI 范例。
我无法生成适当的最小工作示例,主要是由于我对 iOS 开发的新手水平理解,但我确实有一个简单的 SwiftUI 项目可能会有所帮助。
在我的 ContentView.swift:
import SwiftUI
struct ContentView: View {
@State var viewText :String
var myClass :MyClass
var body: some View {
VStack{
Text(viewText)
.padding()
Button("Update Text", action: {
myClass.update()
viewText = myClass.txt
})
}
}
}
class MyClass: NSObject {
var txt :String = ""
var useSetVal :Bool = false
func update(){
if(useSetVal){
setValue("used set val", forKey: "txt")
} else {
txt = "used ="
}
useSetVal = !useSetVal
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
let mc = MyClass()
ContentView(viewText: "", myClass: mc)
}
}
在我的 PracticeApp.swift
import SwiftUI
@main
struct PracticeApp: App {
var body: some Scene {
WindowGroup {
let mc = MyClass()
ContentView(viewText: "", myClass: mc)
}
}
}
在此应用程序中,我希望在按下按钮时看到文本在“used =”和“used setVal”之间切换。相反,当我调用 setValue:
时出现异常Thread 1: "[<Practice.MyClass 0x60000259dc20> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key txt."
我一直在查看答案 here 但由于大多数答案都涉及 xib 和故事板文件(我没有,或者不知道如何找到),我不知道看看它们之间的关系。
顺便说一句,即使我实际尝试修复的应用程序不使用 SwiftUI 并且 setValue 的问题有所不同,但我确实没有 .xib 或 .storyboard 文件或我只是不知道在哪里可以找到它们。
如果有人可以帮助我找出我的示例中的问题,或者可以让我更接近解决实际应用程序的问题(包括如何生成适当的 MWE),我将不胜感激。
我相信我已经写的内容足以解决这个问题(至少一开始是这样),但对于那些感兴趣的人,我想我会添加完整的故事。
全文
我是 iOS 开发的新手,我刚刚获得了旧 iOS 应用程序的所有权。它自 2017 年以来就没有真正被触及过。我注意到一个动画不起作用。虽然我无法验证它是否曾经工作过,但我有充分的理由假设它曾经工作过,但我不能说它何时停止工作。我注意到的一个问题是动画属性应该使用 NSKeyValueCoding.setValue(_:forKey:) 函数更新,但调用该函数时似乎没有任何反应。
我能够通过用我自己的 setValue 函数覆盖来解决这个问题,该函数基本上使用 switch 语句将每个键映射到其对应的值。但是,这并没有修复动画或解释为什么 setValue 函数不起作用。
因为 setValue 函数和 CABasicAnimation.add(_:forKey:) 都依赖于相同的 keyPath,我想知道解决一个问题是否可以帮助我解决另一个问题。我决定专注于 setValue 问题(至少现在)。
当我开始一个新项目作为 MWE 使用时,我注意到 Xcode 13.0 (13A233) 提供的 Storyboard 和 SwiftUI 界面选项都没有启动我的项目结构匹配我现有的项目。我很清楚 SwiftUI 是新的,与我现有的项目有很大不同,但 Storyboard 界面也不熟悉,在阅读教程几分钟后,我未能构建一个能够响应按钮按下的 Storyboard 应用程序(我发现的所有情节提要应用程序教程似乎都是为 Xcode) 的旧版本设置的。
SwiftUI 将要求您使用@ObservedObject 来对对象的变化做出反应。您可以使它符合观察对象和键值操作,如下所示:
struct ContentView: View {
@State var viewText :String
@ObservedObject var myClass :MyClass
var body: some View {
VStack{
Text(viewText)
.padding()
Button("Update Text", action: {
myClass.update()
viewText = myClass.txt
})
}
}
}
class MyClass: NSObject, ObservableObject {
@objc dynamic var txt: String = ""
@Published var useSetVal: Bool = false
func update(){
if(useSetVal){
setValue("used set val", forKey: "txt")
} else {
txt = "used ="
}
useSetVal = !useSetVal
}
}
您需要使 txt
属性 对 Objective-C 可用,以便使其与 KVO/KVC 一起使用。这是必需的,因为键值 Observing/Coding 机制是一项 Objective-C 功能。
所以,要么
class MyClass: NSObject {
@objc var txt: String = ""
,或
@objcMembers class MyClass: NSObject {
var txt: String = ""
这将修复该错误,并应使您的应用按预期运行。但是,正如其他人所说,您需要对代码进行更多更改才能遵守 SwiftUI 范例。