在子协议中指定关联类型

时间:2019-02-27 17:44:04

标签: swift protocols associated-types

是否可以在子协议中定义关联类型,然后将子协议用作iVar类型?

这是我需要实现的:

protocol Coordinator {
    associatedtype ResultValue
    associatedtype ResultError

    func start(completion: @escaping (Result<ResultValue, ResultError>) -> Void)
}

protocol DownloadPermissionCoordinator: Coordinator {
    associatedtype ResultValue = String
    associatedtype ResultError = DownloadPermissionCoordinatorError
}

protocol SomeOtherCoordinator: Coordinator {
    associatedtype ResultValue = Int
    associatedtype ResultError = SomeOtherCoordinatorError
}

然后才能像这样使用它:

final class MyTestClass {
    private let downloadPermissionCoordinator: DownloadPermissionCoordinator
    private let someOtherCoordinator: SomeOtherCoordinator

    init(downloadPermissionCoordinator: DownloadPermissionCoordinator,
         someOtherCoordinator: SomeOtherCoordinator) {
        self.coordinator = coordinator
        self.someOtherCoordinator = someOtherCoordinator
    }
}

您可以想象,Swift不认为我的子协调器协议可用作类型约束。

像这样修改它:

protocol Coordinator2 {
    func start<ResultValue, ResultError>(completion: @escaping (Result<ResultValue, ResultError>) -> Void)
}

不幸的是没有达到目的。

我试图避免委托人使用具体的协调器协议,但是似乎我不能使用通用闭包。有什么建议吗?

p.s。只是为了举例说明协调器的用法,我添加了以下不完整的代码

final class DownloadPermissionCoordinatorImpl: DownloadPermissionCoordinator {
    private let rootViewController: UIViewController
    private let userPermissionService: UserPermissionService

    init(rootViewController: UIViewController,
         userPermissionService: UserPermissionService) {
        self.rootViewController = rootViewController
        self.userPermissionService = userPermissionService
    }

    func start(completion: @escaping (Result<String, ()>) -> Void) {
        guard !userPermissionService.allowsCelularDownload else {
            completion(.success)
            return
        }

        let alertController = ...
        rootViewController.present(alertController, animated: true, completion: nil)
    }
}

extension MyTestClass {
    func doStuffIfAllowed() {
        downloadPermissionCoordinator.start { result in
            switch result {
            case .success: download()
            case .failure: dismiss()
            }
        }
    }
}

0 个答案:

没有答案