如何从Swift扩展访问Objective-C类的私有成员?

时间:2022-09-07 07:40:42

I'm trying to extend an Obj-C class in Swift and make it conform to the Equatable protocoll. This requires to access some private members of the extended class, which the compiler doesn't let me do. What is the correct way to do it without making the private members public?

我正在尝试在Swift中扩展一个Obj-C类,并使其符合Equatable协议。这需要访问扩展类的一些私有成员,编译器不允许我这样做。在没有公开私人会员的情况下,这样做的正确方法是什么?

Swift:

import Foundation

extension ShortDate : Equatable {
}

public func == (lhs: ShortDate, rhs: ShortDate) -> Bool {
    if (lhs.components.year == rhs.components.year)
        && (lhs.components.month == rhs.components.month)
        && (lhs.components.day == rhs.components.day) {
            return true;
    }
    return false;
}

Objective-C:

@interface ShortDate : NSObject<NSCopying, NSCoding> {
    NSDate           *inner;
    NSDateComponents *components; // The date split into components.
}

...

@end

The error:

ShortDate.swift:26:9: 'ShortDate' does not have a member named 'components'

ShortDate.swift:26:9:'ShortDate'没有名为'components'的成员

2 个解决方案

#1


3  

I believe that there is no way to access Objective-C instance variables from Swift. Only Objective-C properties get mapped to Swift properties.

我相信没有办法从Swift访问Objective-C实例变量。只有Objective-C属性才会映射到Swift属性。

#2


0  

I came across this question while trying to find a way to access a private variable of a class from one of the SDKs we use. Since we don't have or control the source code we can't change the variables to properties. I did find that the following solution works for this case:

我试图找到一种从我们使用的SDK之一访问类的私有变量的方法时遇到了这个问题。由于我们没有或没有控制源代码,我们无法将变量更改为属性。我确实发现以下解决方案适用于这种情况:

extension ObjcClass {
    func getPrivateVariable() -> String? {
        return value(forKey: "privateVariable") as? String
    }

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

Overriding value(forUndefinedKey:) is optional. value(forKey:) will crash if the private variable doesn't exist on the class unless you override value(forUndefinedKey:) and provide a default value.

覆盖值(forUndefinedKey :)是可选的。如果类上不存在私有变量,则值(forKey :)将崩溃,除非您覆盖值(forUndefinedKey :)并提供默认值。

#1


3  

I believe that there is no way to access Objective-C instance variables from Swift. Only Objective-C properties get mapped to Swift properties.

我相信没有办法从Swift访问Objective-C实例变量。只有Objective-C属性才会映射到Swift属性。

#2


0  

I came across this question while trying to find a way to access a private variable of a class from one of the SDKs we use. Since we don't have or control the source code we can't change the variables to properties. I did find that the following solution works for this case:

我试图找到一种从我们使用的SDK之一访问类的私有变量的方法时遇到了这个问题。由于我们没有或没有控制源代码,我们无法将变量更改为属性。我确实发现以下解决方案适用于这种情况:

extension ObjcClass {
    func getPrivateVariable() -> String? {
        return value(forKey: "privateVariable") as? String
    }

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

Overriding value(forUndefinedKey:) is optional. value(forKey:) will crash if the private variable doesn't exist on the class unless you override value(forUndefinedKey:) and provide a default value.

覆盖值(forUndefinedKey :)是可选的。如果类上不存在私有变量,则值(forKey :)将崩溃,除非您覆盖值(forUndefinedKey :)并提供默认值。