是否可以在Swift中创建一个通用的闭包?

时间:2014-08-28 09:22:01

标签: ios generics swift closures

func myfunc<T>(i:T) -> T {
    return i
}

是否可以使这个泛型函数成为闭包?

let myfunc = { <T>(i:T) -> T in
    return i
}

这不起作用......

4 个答案:

答案 0 :(得分:13)

不,因为变量和表达式不是通用的。只有通用函数和泛型类型。


澄清一下:在某些语言中,您可以使用通用量词的类型,例如forall a. a -> a。但在Swift中,类型不能具有通用量词。因此表达式和值本身不是通用的。函数声明和类型声明可以是通用的,但是当您使用这样的泛型函数或这种泛型类型的实例时,会选择某种类型(可以是实数类型或类型变量)作为类型参数,然后你得到的价值不再是通用的。

答案 1 :(得分:6)

可能您需要这样的东西。

类型声明:

typealias ResultClosure<T> = (ResultCode, String?, T?) -> Void

函数声明:

func loginUser(userName: String, password: String, resultHandler: ResultClosure<TokenModel>?)

用法:

    NetConnector.shared.loginUser(userName: userName ?? "", password: password ?? "") { (code, message, data) in
        self.display?.unlockScreen()
        if code == .success {
            if let activeToken = data {
                AppData.shared.userToken = activeToken
            }
            self.display?.showHome()
        } else {
            self.display?.showError(errorMessage: message)
        }
    }

答案 2 :(得分:0)

我找到了另一种方法,您可以在闭包中使用Anyobject并将任何值传递给您的方法。

typealias genericCompletion<T:AnyObject> = ((Bool,T,String) -> Void)
struct Student {
    var name:String = "Kishore"
    var age : String = "125"
}
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        self.createAGenericReturn { (success, object, message) in

        }

        self.createStructGeneric { (success, student, message) in

        }

    }


    func createAGenericReturn(callback:@escaping(genericCompletion<AnyObject>)){
        callback(true,434.433 as AnyObject,"kishoreTest")
    }

    func createStructGeneric(callback:@escaping(genericCompletion<AnyObject>)){
        callback(true,Student.init() as AnyObject,"kishoreTest")
    }

}

在这里您可以看到我提到Generic as Anyobject typealias genericCompletion =((Bool,T,String)-> Void),因此您可以将任何值传递给它。

答案 3 :(得分:0)

如前所述,Swift中的变量不能为通用变量,因此无法创建由调用者指定其通用类型的闭包。但是,有一些解决方法:

使用SE-253,可以使任意(名义)类型可调用。因此,我们可以声明一个具有通用callAsFunction方法的(非通用)结构,而不是声明一个通用闭包:

struct MyFunc {
    func callAsFunction<T>(_ i: T) -> T {
        return i
    }
}

现在,我们可以声明一个可以使用通用值调用的非通用变量:

let myFunc = MyFunc()
let x = myFunc(42) // -> Int
let y = myFunc("foo") // -> String

请注意,此变通办法并不适用于所有情况,但在某些情况下可能会有所帮助。