3

I was a few days ago from Objective-C to write Swift language, in the project I have encountered a problem.This problem is when using respondsToSelector ("testEnum:") function to check whether to implement the function of the testEnum:,if the param is the case, it will return false, I have tried other types, it will return true, do not know what is the reason, see the following code, to help me solve it, thank you very much!

 enum TestEnum {
        case A
        case B
        case C
    }

    protocol TestAProtocol: NSObjectProtocol {
        func testEnum(testEnum: TestEnum);
        func testInt(testInt: Int);
    }

    class TestA: NSObject {
        var delegate: TestAProtocol?;

        func executeDelegateCallBack() {
            if (delegate != nil && delegate!.respondsToSelector(Selector("testEnum:"))) { // delegate!.respondsToSelector(Selector("testEnum:")) return false ?
                delegate?.testEnum(TestEnum.A);
            }

            if (delegate != nil && delegate!.respondsToSelector(Selector("testInt:"))) { // delegate!.respondsToSelector(Selector("testInt:")) return true ?
                delegate?.testInt(0);
            }
        }
    }

    class TestB: NSObject, TestAProtocol {
        func initTestB () {
            let testA: TestA = TestA();
            testA.delegate = self;
            testA.executeDelegateCallBack();
        }

        // mark TestAProtocol
        func testInt(testInt: Int) {

        }

        func testEnum(testEnum: TestEnum) {

        }
    }
fly_basket
  • 49
  • 7
  • 2
    Its not the answer to your question, but your || should be && - You want delegate to be non-nil and to respond to the selector – Paulw11 Dec 15 '15 at 08:03
  • Well, I'm writing a test example, not too much attention, thank you, I alter it! – fly_basket Dec 15 '15 at 08:09

1 Answers1

6

respondsToSelector() uses the Objective-C runtime and works only with methods which are Objective-C compatible. Swift enums can only be represented in Objective-C if they are marked with @objc, and that requires that they have an integer raw value.

So with

@objc enum TestEnum : Int {
    case A
    case B
    case C
}

your respondsToSelector(Selector("testEnum:") will return true.

Note however that testing for the presence of a method makes only sense with optional protocol methods, and these are only available for @objc protocols, for example:

@objc enum TestEnum : Int {
    case A
    case B
    case C
}

@objc protocol TestAProtocol: NSObjectProtocol {
    optional func testEnum(testEnum: TestEnum)
    func testInt(testInt: Int)
}

And then it is much simpler to use optional chaining instead of respondsToSelector:

func executeDelegateCallBack() {
    delegate?.testEnum?(.A)

    // ...
}

or more detailed:

func executeDelegateCallBack() {
    if let testEnum = delegate?.testEnum {
        testEnum(.A)
    } else {
        print("delegate is `nil` or does not respond to `testEnum`")
    }

    // ...
}
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382