简体   繁体   中英

swift method accept parameter if conform a protocol

i have a protocol named WebServiceProtocol and method like this :

class func executeRequest(delegate:__SOMETHING__,url:String,postParameters:[String:String],headerParameters:[String:String]){
   //Do something and call delegate
}

i want to have a conditional argument that check if input conform WebServiceProtocol Accept it.

i'm tying to write a global class function that work with every input , maybe a ViewController or NSObject class.

in java for classes we did like this :

<? extends SomeClass>

Edit 在此处输入图片说明 WebService.swift

import Foundation

protocol WebServiceProtocol {
    func onDataReceived(data:NSDictionary!)
    func onFailure()
}

class WebService:NSObject{

    class func executeRequest(delegate:WebServiceProtocol,url:String,postParameters:[String:String],headerParameters:[String:String]){
        if let URL: NSURL = NSURL(string: url){
            var request:NSMutableURLRequest = NSMutableURLRequest(URL:URL)
            request.HTTPMethod = "POST"
            request.HTTPBody = arrayToHttpParams(postParameters).dataUsingEncoding(NSUTF8StringEncoding)
            NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()){
                    response, data, error in
                    if error == nil {
                        if let jsonString = NSString(data: data, encoding: NSUTF8StringEncoding){
                            if let dictionary = Helper.parseJson(jsonString as String) {
                                delegate.onDataReceived(dictionary)
                                println(dictionary)
                                return;
                            }
                        }
                        println("failure !")
                        delegate.onDataReceived(nil)
                    }
                    else{
                        delegate.onFailure()
                    }
            }
        }
    }

    class func arrayToHttpParams(params:[String:String])->String{
        var mergedParams = [String]();
        for (key,value) in params {
            mergedParams.append(key+"="+value)
        }
        return "&".join(mergedParams);
    }
}

Authentication.swift

protocol AuthenticationLoginProtocol {
    func onSuccess(data:NSDictionary)
    func onFailure(data:NSDictionary)
}

class Authentication:NSObject,WebServiceProtocol{

   func attempLogin(delegate:ViewController,emial:String,password:String){

        var params = [String:String]();
        params["key1"]="value1"
        params["key2"]="value2"

        WebService.executeRequest(self, url: "", postParameters: params, headerParameters: params)

    }

    func onDataReceived(data: NSDictionary!) {

    }
    func onFailure() {

    }

}

Update

You are trying to reference an instance in a type method. Instead of this,

WebService.executeRequest(self, url: "", postParameters: params, headerParameters: params)

write this:

WebService.executeRequest(Authentication.self, url: "", postParameters: params, headerParameters: params)

Then later in for example Authentication :

class Authentication: NSObject, WebServiceProtocol {

    // ...

    func someMethod() {
        WebService.executeRequest(self, url: "", postParameters: ["1": "2"], headerParameters: ["1": "2"])
    }

    // ...
}

Original answer

You could make a generic function with a type constraint for your protocol:

func myFunc<T: WebServiceProtocol>(input: T) {
  // input surely conforms to WebServiceProtocol
}

This way, T can be any type, as long as it conforms to the WebServiceProtocol .

For more details, see Type Constraints here .

If you make the input take your protocol as the parameter type, the compiler will only compile if the parameter for that function implements that protocol, like above.

import UIKit

protocol WebServiceProtocol {

}

class ViewController: UIViewController {

    @IBOutlet weak var testLabel: UILabel!

    func takeProtocolAsInput(input: WebServiceProtocol) {

    }

    func otherFunc() {
        takeProtocolAsInput(A())

        // Compile-time error: B does not conform to WebServiceProtocol
        takeProtocolAsInput(B())
    }
}

class A: WebServiceProtocol {

}

class B {

}

@József Vesza solution is good because Xcode will let you know if you're trying to pass in an object that doesn't conform to WebServiceProtocol . However, if you want to be able to pass anything (as specified in the question) to your function you could do the following:

func myFunc(obj: Any) {
    if let webService = obj as? WebServiceProtocol {
        // Do stuff with webService...
    }
}

You can make that method generic

class func executeRequest<T: WebServiceProtocol>(delegate: T,url:String,postParameters:[String:String],headerParameters:[String:String]) {

}

There is an article about how this approach and @Will M.'s differ each other.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM