0

I have multiple classes with the same static variable. I get the currentInstance of each class at runtime(AnyObject?). Then I am trying to access static variables by getting a class from instance using type(of: instance) method. But when trying to get the static variable it throws me an error - Value of type 'AnyObject.Type' has no member . Here is pseudo code.

public extension Reader {
  open static var funcDictionary = [String: readerFuncs]() //ReaderFuncs is an enum of functions
}

public extension Library {
  open static var funcDictionary = [String: libraryFuncs]() 
}

public extension ReaderMenu {
  open static var funcDictionary = [String: readerMenuFuncs]() 
}


import Foundation
open class TestClass: NSObject {
  open func executeFunction(currentInstance: AnyObject) { // I get current instance at runtime. And I have checked that I get the correct value
  var count = type(of: currentInstance).functionDictionary.count // Error: Value of type 'AnyObject.Type' has no member funcDictionary 
}

I would like to know how to access static variables when you only have the instance of the class available. I have used .classforCoder() too but it doesn't work. All the files have the same target membership too.

3
  • You're going to have to create a protocol that requires the open static var funcDictionary and then alter your TestClass function to open func executeFunction<T: ProtocolName>(currentInstance: T). Then rather than using type(of:, you can use T.functionDictionary.count Commented Sep 9, 2016 at 1:43
  • What do your enums look like? Commented Sep 9, 2016 at 1:43
  • I have updated my answer and tested it in playground, let me know if it works for you. Commented Sep 9, 2016 at 2:37

1 Answer 1

1

You should use generic types in your TestClass executeFunction method, but we need a common reference to all three of your classes Reader, Library and ReaderMenu. To do that, we will create a protocol that each class has to conform to.

protocol Funcable {

    associatedtype FuncsEnum

    static var funcDictionary: [String:FuncsEnum] { get set }
}

Now each class inherits from Funcable, they are all required to have a typealias that defines the type of enum in the funcDictionary.

class Reader: Funcable {

    typealias FuncsEnum = Reader.Funcs

    static var funcDictionary = [String:FuncsEnum]()

    enum Funcs {
        case A
        case B
    }
}

class Library: Funcable {

    typealias FuncsEnum = Library.Funcs

    static var funcDictionary = [String:FuncsEnum]()

    enum Funcs {
        case C
        case D
    }
}

class ReaderMenu: Funcable {

    typealias FuncsEnum = ReaderMenu.Funcs

    static var funcDictionary = [String:FuncsEnum]()

    enum Funcs {
        case E
        case F
    }
}

You can define your enums outside of the classes if you like, but I've moved them inside to make it more reusable. Anyway back at the TestClass, we can use Generic Type Token T which is a mirror of the class of the given currentInstance.

class TestClass: NSObject {

    func executeFunction<T: Funcable>(currentInstance: T) {

        print(T.funcDictionary.count)
    }
}

To access the enums individually e.g. Reader.Funcs instead of readerFuncs

UPDATE

We can just instantiate the currentInstance on our own to make it work.

let testInstance = TestClass()

Reader.funcDictionary.updateValue(.A, forKey: "a")

testInstance.executeFunction(currentInstance: Reader()) // prints 1

Library.funcDictionary.updateValue(.C, forKey: "c")
Library.funcDictionary.updateValue(.D, forKey: "d")

testInstance.executeFunction(currentInstance: Library()) // prints 2
Sign up to request clarification or add additional context in comments.

6 Comments

In my driver program I get the currentInstance - var currenInstance? = someClass.getInstance(). var test = TestClass(). test.executeFunction(currentInstance: currenInstance ) gives an error saying "Argument of type AnyObject? does not confirm to expected type Funcable ". This is because getInstance return a type of AnyObject. But since this AnyObject is of type Library, Reader (which implement Funcable) I am not sure why this not working.
That's because currenInstance is of type AnyObject? and executeFunction requires a type that conforms to protocol Funcable. Where does someClass.getInstance() come from?
It comes from another class. Something like :code class StateOption { getInstance(state: state) -> AnyObject? { case(state) { case .library: return Library() case .reader: return Reader() } } In driver program: var stateOption = StateOption() var currentInstance = stateOption.getInstance(state: state) var testInstance = TestClass() testInstance.executeFunction(currentInstance: currentInstance!) Additionally Funcable also implements class protocol
Okay, just change getInstance(state: state) -> AnyObject? to getInstance(state: state) -> Funcable?
Had tried that. Gives me an error --- protocol 'Funcable' can only be used as a generic constraint because it has Self or associated type requirements
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.