如何在 Obj-C 或 Swift 中访问私有实例变量?

Posted

技术标签:

【中文标题】如何在 Obj-C 或 Swift 中访问私有实例变量?【英文标题】:How do I access private instance variables in Obj-C or Swift? 【发布时间】:2018-08-01 04:58:02 【问题描述】:

我正在尝试在 macOS 上的 Swift 中访问 MKMapSnapshotter 的私有实例变量 _lodpiSnapshotCreator_hidpiSnapshotCreator

感谢 class-dump,我知道他们在那里 (see here):

@interface MKMapSnapshotter : NSObject

    [...]
    VKMapSnapshotCreator *_lodpiSnapshotCreator;
    VKMapSnapshotCreator *_hidpiSnapshotCreator;

但无论我做什么,我都无法抓住它们。

这是我检查是否可以访问它们的方式:

let snapshotter = MKMapSnapshotter(options: snapshotOptions)

let varNames = ["_lodpiSnapshotCreator", "_hidpiSnapshotCreator"]
for varName in varNames 
    if let testIVar = class_getInstanceVariable(MKMapSnapshotter.self, varName) 
        if let test = object_getIvar(snapshotter, testIVar) as? VKMapSnapshotCreator 
            print(test)
         else 
            print("Got ivar, but \(varName) is still nil (getInstanceVariable)")
        
     else 
        print("\(varName) is nil (getInstanceVariable)")
    

奇怪的是,class_getInstanceVariable 不会返回 nil,但 object_getIvar 会。

Got ivar, but _lodpiSnapshotCreator is still nil (getInstanceVariable)
Got ivar, but _hidpiSnapshotCreator is still nil (getInstanceVariable)

我在这里束手无策。我可以通过 Google 找到的只是人们推荐使用 class_getInstanceVariable(我已经在使用)和 key-value-coding(根本不起作用)。

这一定是以前做过的。谁能帮帮我?

编辑:到目前为止,我已经尝试过:

@interface MKMapSnapshotter() 
    @public VKMapSnapshotCreator *_lodpiSnapshotCreator;
    @public VKMapSnapshotCreator *_hidpiSnapshotCreator;


@end

编译成功,但是在尝试使用它时,Swift 一直坚持认为成员 _lodpiSnapshotCreator 和 _hidpiSnapshotCreator 不存在。

【问题讨论】:

我不知道您要对这些变量做什么,但为 MKMapSnapshotter 类编写扩展可能会更容易 转到 MKMapSnaphotter 并为要访问的变量创建 getter 和 setter 方法。 @AgentSmith 尝试访问我的 getter 方法会导致 [MKMapSnapshotter _hidpiSnapshotCreator]: unrecognized selector sent to instance。 我想扩展也行不通,我打算写一个测试分机来查看所有内容,但我找不到提到这些lodpiSnapshotCreatorhidpiSnapshotCreator...无论如何,在 ios 中看到 dpi 有点奇怪,我通常只在 android 项目中看到这些 @JacobBoyd 这是针对 macOS 的。我可能应该在问题中说,哎呀 【参考方案1】:

由于我们没有或控制源代码,我们无法将变量更改为属性。刚刚尝试过这适用于您的情况:

extension MKMapSnapshotter 
   func getPrivateVariable() -> String? 
       return value(forKey: "_lodpiSnapshotCreator") as? String
   

   open override func value(forUndefinedKey key: String) -> Any? 
       if key == "_lodpiSnapshotCreator" 
           return nil
       
       return super.value(forUndefinedKey: key)
   

您可以找到有关此here 的更多信息。

如果这不起作用,那么我相信没有办法从 Swift 访问 Objective-C 实例变量。只有 Objective-C 属性被映射到 Swift 属性。

希望这会有所帮助!

【讨论】:

getPrivateVariable() 只为我返回 nil。 @PeterW。忘了提到覆盖 value(forUndefinedKey:) 是可选的。如果私有变量在类中不存在 value(forKey:) 将崩溃,除非您覆盖 value(forUndefinedKey:) 并提供默认值。 我真的只需要那个属性,所以很遗憾这对我不起作用。不管怎样,谢谢! 你能把VKMapSnapshotCreator *转换成String吗?

以上是关于如何在 Obj-C 或 Swift 中访问私有实例变量?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 swift 中从可加载包创建主体类的实例

如何在同一框架内访问 Objective-C 中的内部 Swift 类?

Swift 语言中如何使用私有属性? [复制]

可互操作的 Obj-C typedef NS_ENUM 到 swift

可互操作的 Obj-C typedef NS_ENUM 到 swift

请求音乐库权限 swift 或 obj-c