简体   繁体   English

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

[英]is it possible to create a generic closure in Swift?

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

is it possible to make this generic function a closure?是否可以使这个通用函数成为闭包?

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

this doesn't work...这不起作用...

No, because variables and expressions can't be generic.不,因为变量和表达式不能是通用的。 There are only generic functions and generic types.只有泛型函数和泛型类型。


To clarify: In some languages you can have types with a universal quantifier, like forall a. a -> a澄清一下:在某些语言中,您可以拥有带有通用量词的类型,例如forall a. a -> a forall a. a -> a . forall a. a -> a But in Swift, types cannot have a universal quantifier.但是在 Swift 中,类型不能有全称量词。 So expressions and values cannot be themselves generic.所以表达式和值本身不能是通用的。 Function declarations and type declarations can be generic, but when you use such a generic function or an instance of such a generic type, some type (which could be a real type or a type variable) is chosen as the type argument, and thereafter the value you get is no longer itself generic.函数声明和类型声明可以是泛型的,但是当您使用这样的泛型函数或这样的泛型类型的实例时,某些类型(可以是实类型或类型变量)被选为类型参数,然后您获得的价值本身不再是通用的。

Probably you need something like this.可能你需要这样的东西。

Type declaration:类型声明:

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

Function declaration:函数声明:

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

Usage:用法:

    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)
        }
    }

As mentioned, variables in Swift cannot be generic, so creating a closure, whose generic types are specified by the caller is not possible.如前所述,Swift 中的变量不能是泛型的,因此创建一个闭包,其泛型类型由调用者指定是不可能的。 However, there are workarounds:但是,有一些解决方法:

With SE-253 , it is possible to make arbitrary (nominal) types callable.使用SE-253 ,可以使任意(名义)类型可调用。 So instead of declaring a generic closure, we can declare a (non-generic) struct that has a generic callAsFunction method:因此,我们可以声明一个具有通用callAsFunction方法的(非通用)结构,而不是声明一个通用闭包:

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

Now, we can declare a non-generic variable that we can call with a generic value:现在,我们可以声明一个可以使用泛型值调用的非泛型变量:

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

Note that this workaround doesn't apply to all situations, but it can be helpful in some.请注意,此解决方法并不适用于所有情况,但在某些情况下可能会有所帮助。

I have found some alternative way , you can use Anyobject in your closure and pass any values to your method .我找到了一些替代方法,您可以在闭包中使用 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")
    }

}

Here you can see I mentioned Generic as Anyobject typealias genericCompletion = ((Bool,T,String) -> Void) , So you can pass any values to it .在这里你可以看到我提到 Generic 作为 Anyobject typealias genericCompletion = ((Bool,T,String) -> Void) ,所以你可以向它传递任何值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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