Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access private members of an Objective-C class from a Swift extension?

I'm trying to extend an Objective-C class in Swift and make it conform to the Equatable protocol. 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?

My Swift code:

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 I'm getting:

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

like image 859
Mike Lischke Avatar asked Oct 26 '14 12:10

Mike Lischke


2 Answers

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:

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.

like image 174
Joe Waller Avatar answered Oct 10 '22 02:10

Joe Waller


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

like image 40
newacct Avatar answered Oct 10 '22 02:10

newacct