- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我必须通过字符串名称表示形式为属性设置值。
import Foundation
@objc class A:NSObject {
var x:String = ""
}
var a = A()
a.x = "ddd"
print(a.x)
a.setValue("zzz", forKey:"x")
print(a.x)
在编译过程中出现奇怪的错误:
main.swift:4:2: error: only classes that inherit from NSObject can be declared @objc
@objc class A:NSObject {
~^~~~~
main.swift:13:1: error: value of type 'A' has no member 'setValue'
a.setValue("zzz", forKey:"x")
^ ~~~~~~~~
有人知道发生了什么吗?
PS:可在 Swift 4.0 和 3.1.1 (Ubuntu 16.04.3 LTS) 上重现
编辑:
import Foundation
@objc class A:NSObject {
@objc dynamic var x:String = ""
}
var a = A()
a.x = "ddd"
print(a.x)
a.setValue("zzz", forKeyPath:"x")
print(a.x)
输出:
错误:只能声明继承自 NSObject 的类 @objc@objc A 类:NSObject {
错误:无法将属性标记为@objc,因为其类型无法在 Objective-C 中表示 @objc 动态变量 x:String = ""
注意:Swift 结构不能在 Objective-C 中表示 @objc 动态变量 x:String = ""
错误:类型“A”的值没有成员“setValue”a.setValue("zzz", forKeyPath:"x")
编辑 2:就像“c-style”一样尝试:
func set<T>(_ val:T, forKey key:String) {
print("SET:\(self) \(key) to \(val)")
let ivar: Ivar = class_getInstanceVariable(type(of: self), key)!
let pointerToInstanceField:UnsafeMutableRawPointer = Unmanaged.passRetained(self).toOpaque().advanced(by: ivar_getOffset(ivar))
let pointer = pointerToInstanceField.assumingMemoryBound(to: T.self)
pointer.pointee = val
}
它运行良好,但会在递归调用中导致错误访问。可能有一些保留/释放问题。会挖斗。也不适用于 Linux(如答案中所述)
最佳答案
文档
Swift without the Objective-C Runtime: Swift on Linux does not depend on the Objective-C runtime nor includes it. While Swift was designed to interoperate closely with Objective-C when it is present, it was also designed to work in environments where the Objective-C runtime does not exist.
https://swift.org/blog/swift-linux-port/
这是明确的,只要它声明:
value of type 'A' has no member 'setValue'
基本说明底层没有KVC机制。 setValue
方法来自 Objective-C 运行时,Linux 上没有。因此,这是行不通的,您想要完成的事情根本不可能。
除此之外,以下规则适用于具有 Obj-C 运行环境的系统:
Swift objects that inherit from NSObject or one of its subclasses are key-value coding compliant for their properties by default. Whereas in Objective-C, a property’s accessors and instance variables must follow certain patterns, a standard property declaration in Swift automatically guarantees this. On the other hand, many of the protocol’s features are either not relevant or are better handled using native Swift constructs or techniques that do not exist in Objective-C. For example, because all Swift properties are objects, you never exercise the default implementation’s special handling of non-object properties.
Swift APIs that are callable from Objective-C must be available through dynamic dispatch. However, the availability of dynamic dispatch doesn’t prevent the Swift compiler from selecting a more efficient dispatch approach when those APIs are called from Swift code.
You use the @objc attribute along with the dynamic modifier to require that access to members be dynamically dispatched through the Objective-C runtime. Requiring this kind of dynamic dispatch is rarely necessary. However, it is necessary when using APIs like key–value observing or the method_exchangeImplementations function in the Objective-C runtime, which dynamically replace the implementation of a method at runtime.
Declarations marked with the dynamic modifier must also be explicitly marked with the @objc attribute unless the @objc attribute is implicitly added by the declaration’s context. For information about when the @objc attribute is implicitly added, see Declaration Attributes in The Swift Programming Language (Swift 4).
为了与 KVO 兼容,元素也必须声明为动态的(对于 KVC,从 NSObject
继承就足够了):
@objc dynamic var x:String = ""
如果 String
无法解决问题,请尝试使用 NSString
。
如果两者都没有帮助,这似乎是 Linux 特有的问题,它似乎不支持 KVC/KVO 机制(这也是可以理解的)。
附言使用提供的代码,您的问题也在 Mac 上的 Xcode 中重现。
关于swift - 只有继承自 NSObject 的类才能声明为 @objc,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46849486/
SWIFT代码 print("1", NSObject() == NSObject()) print("2", ObjectIdentifier(NSObject()) == ObjectIdenti
保留在 NSObject 协议(protocol)中声明。 因此NSObject类和NSProxy类实现了它。 然而 NSProxy 和 NSObject 类都有一个分配。 为什么 alloc 没有在
我有一个已在App Store中发布的应用程序。大约有1%-2%的用户报告该应用程序崩溃了。这不是完全意外的行为,因此我要求提供崩溃日志。这是最后一个异常回溯(实际显示问题的部分): Last E
我有一个自定义 NSObject 类,可以调用 People,还有一个来自 CloudMade RMMarker.h 的名为 RMMarker 的类。 RMMarker 类有一个名为 data 的属性
这是崩溃报告,不知道为什么。我使用 AFHTTPRequestOperation setCompletionBlockWithSuccess:failure: 调用电话。在完成 block 中,我得到
应用程序有时会因 [NSObject(NSObject) doesNotRecognizeSelector:] 而崩溃,选择器为 [UIImageView setImage:]。 我通过设置异常断点捕
崩溃报告: 0 CoreFoundation!__exceptionPreprocess + 0x7c 1 libobjc.A.dylib!objc_exception_throw
我正在将我的整个项目从 Objective-C 转换为 Swift...在转换时我遇到了这个问题:“无法将‘Facility’类型的值转换为预期的参数类型“Facility!” 错误出现在我提到的最后
我在将数组[String]保存到核心数据时遇到问题。在核心数据中,我设置了字段“countires”的类型 - 可转换。 我通过以下方式添加数据: filters!.countries = selec
假设您有一个返回 NSDictionary 的方法。要构建字典,您可能需要创建一个 NSMutableDictionary。返回字典的不可变副本而不是仅返回可变字典是否有任何必要或优势? 例如 - (
在一个小型 RTS 项目中,我有一个按钮列表,每个按钮都分配有一个构建对象。有些建筑物非常通用,但其他建筑物则非常特殊,因此我将某些建筑物作为子类。 当我创建一个按钮列表时,每个按钮都有一个 PEHo
这个问题在这里已经有了答案: Objective-C: Property / instance variable in category (6 个答案) Objective-C: Instance
我实际上想知道如何从 NSObject 或任何其他类访问 encodeWithCoder、init 等方法而不继承 NSObject 类。 因为我读到如果我们从 NSObject 类继承,那么它在 S
我正致力于从 Objective-C 教程转换此委托(delegate)协议(protocol)函数,但在尝试通过使用下标返回基于键的值来访问字典中的值时遇到错误。我不太确定这里的错误是什么意思。任何
在我的 Swift 应用程序中,我有一个类: open class CustomCluster : NSObject { open var coordinate = CLLocationCoo
我有一个字典/数组,看起来像这样: var myArray: [[String:NSObject]] = [] let newItem = [ [
这很奇怪,我可以使用 Xcode 5 (5A1413) 在模拟器、iPhone 4S 和 iPhone 5 中运行我的应用程序而没有任何问题,但是当我将应用程序提交到 iTunes 商店时被拒绝并且此
我使用 NSKeyedArchiver.archivedDataWithRootObject(obj) 将对象转换为 NSData。 archivedDataWithRootObject(obj) 方
背景。 请考虑以下步骤: 1) 在 Xcode 中创建一个新的“单 View 应用程序”。 2)创建类NSObject+Extension.h和.m文件: // .h @interface NSObj
在 ARC 环境中遇到一些小问题。创建一个将 View 添加到父 View 的 NSObject - 它基本上是一个可以处理一些文本并显示它的“弹出类”。 在 View Controller 中它被实
我是一名优秀的程序员,十分优秀!