prabodhprakash
prabodhprakash

Reputation: 3927

Calling method on a struct that implements a protocol

UPDATE START It was because this array was coming from Objective-C and there were some screw-ups happening in the whole process. Needed some fixes, but all the answers below are correct. UPDATE END

I've a protocol as below

protocol SomeProtocol
{
    func someFunctionProtocol
}

There is a struct that implements this protocol as

struct SomeStruct: SomeProtocol
{
   ....
}

Now, at runtime, I get an argument arg: Any that I know for sure will implement SomeProtocol

How should I call this protocol method on arg. I have tried let ob = arg as! HanselProviderProtocol, however this gives me runtime error Could not cast value of type '_SwiftValue' (0x111952720) to 'SomeProtocol' (0x111957158)

The images below show that it is not working

Struct Defn

===== Debug

Upvotes: 2

Views: 248

Answers (4)

dirtydanee
dirtydanee

Reputation: 6151

Type cast the Any type to the struct type, not the protocol.

guard let ob = arg as? SomeStruct else { 
 print("invalid type")
 return 
}

ob.someFunctionProtocol()

EDIT

Or just check with the is keyword.

 let foo: Any = SomeStruct()

 if foo is SomeProtocol {
   // you can safely use force unwrapping here, because the condition above returned true
   (foo as! SomeProtocol).someFunctionProtocol()
 }

If you would be using SwiftLint, you can disable the force cast warning or error with the following command:

// swiftlint:disable:this force_cast

Upvotes: 1

shallowThought
shallowThought

Reputation: 19602

In Swift3, you can cast the argument of type Any to a protocol:

protocol SomeProtocol {
    func someFunctionProtocol()
}

struct SomeStruct: SomeProtocol {
    func someFunctionProtocol() {
        print("Yep")
    }
}

func test(arg: Any) {
    if let castee = arg as? SomeProtocol {
        castee.someFunctionProtocol()
    }
}

test(arg: SomeStruct())

Prints:

Yep

Upvotes: 2

jrturton
jrturton

Reputation: 119242

If you have a value of Any type, you can test for conformance and execute like so:

(arg as? SomeProtocol)?.someFunction() 

Or, if you want it to have wider scope:

guard let conformer = arg as? SomeProtocol else { return }
conformer.someFunction()

Upvotes: 1

Andrey Gershengoren
Andrey Gershengoren

Reputation: 916

If there could be more different structs implementing the protocol, use:

protocol SomeProtocol {
    func a()
}

struct SomeStruct: SomeProtocol {
    func a() {
        print("a called from SomeStruct")
    }
}

let x = SomeStruct() as Any // Just as an example

if let x = x as? SomeProtocol {
    x.a()
}

Upvotes: 1

Related Questions