8

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'

Paulo Mattos
  • 16,310
  • 10
  • 64
  • 73
Mike Lischke
  • 36,881
  • 12
  • 88
  • 141
  • Did you add proper header to Swift header: `YourAppName-Bridging-Header.h`? – Maxim Shoustin Oct 26 '14 at 12:23
  • Yes, sure, the bridging header is in place and I can use the ShortDate class in my Swift code. I simply want to add comparison using operators instead of member functions. – Mike Lischke Oct 26 '14 at 12:25

2 Answers2

6

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.

Joe Waller
  • 1,882
  • 3
  • 19
  • 24
5

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

newacct
  • 110,405
  • 27
  • 152
  • 217