如何创建通用完成关闭?

时间:2018-09-23 22:06:46

标签: swift generics closures

我有以下协议:

protocol RESTAPIprotocol {
    associatedtype T: Object, Decodable
}

extension RESTAPIprotocol {

    func getList(sinceSyncToken: String = "",
                 pageLimit: Int = 100,
                 progress: Moya.ProgressBlock? = nil,
                 completion:@escaping (_ list: [T]?, _ error: AppError?) -> Void) { ... }

和对象:

final class RLMOrganization: RLMDefaults {
    typealias T = RLMOrganization
}

final class RLMProject: RLMDefaults {
    typealias T = RLMProject
}

final class RLMLocation: RLMDefaults {
    typealias T = RLMLocation
}

想要这样使用它:

class SyncEngine {

    let listCompletionClosure = { (_ list: [T]?, _ error: AppError?) -> Void in  ... }


    func syncOrganizations() {
        // Sync down from server and update our local DB.
        organizationsDAL.getList(sinceSyncToken: organizationsDAL.getLastSyncToken(), completion: listCompletionClosure)
    }

但是得到错误:

enter image description here

哪种方式有意义,但不了解如何将RESTAPIprotocol中使用的泛型传递给泛型闭包?

目标是尝试完成以下任务:

func syncOrganizations() {
    organizationsDAL.getList(sinceSyncToken: organizationsDAL.getLastSyncToken(), completion: listCompletionClosure)
}

func syncProjects() {
    projectsDAL.getList(sinceSyncToken: projectsDAL.getLastSyncToken(), completion: listCompletionClosure)
}

func syncLocations() {
    locationsDAL.getList(sinceSyncToken: locationsDAL.getLastSyncToken(), completion: listCompletionClosure)
}

1 个答案:

答案 0 :(得分:0)

将其更改为“

let listCompletionClosure = { (_ list: [RLMOrganization]?, _ error: AppError?) -> Void in  ... }

完成句柄需要具体的类型,并且您已经在T = RLMOrganization类的上下文中定义了RLMOrganization

编辑:闭包不是通用的,但函数可以:

func listCompletion<T: Decodable>(list: [T]?, error: AppError?) {
    // you must cast `list` to a  concrete type
}

func syncOrganizations() {
    organizationsDAL.getList(sinceSyncToken: organizationsDAL.getLastSyncToken(), completion: listCompletion)
}

func syncProjects() {
    projectsDAL.getList(sinceSyncToken: projectsDAL.getLastSyncToken(), completion: listCompletion)
}

func syncLocations() {
    locationsDAL.getList(sinceSyncToken: locationsDAL.getLastSyncToken(), completion: listCompletion)
}