【问题标题】:Swift generics with default value具有默认值的 Swift 泛型
【发布时间】:2016-09-14 17:43:32
【问题描述】:

我正在尝试为应用程序中的每个回调实现一些单一的解决方案。所以我希望任何回调都使用同一个类,或者至少是类家族。

  • 每次回调都可能成功或失败。
  • 如果成功,可以 包含一些运算结果。
  • 如果不是,它可以包含有关失败的信息。

常见的回调用法如下所示:

func foo(callback: ((success: Bool, result: Result?, error: Error?) -> Void)?) { }

或者:

func foo(success: ((result: Result) -> Void)?, failure: ((error: Error) -> Void)?) { }

我不喜欢他们中的任何一个。我想为每个回调提供一个优雅的解决方案。我在Alamofire library 中发现了类似的东西。

    enum CallbackResult<T, V> {
        case success(value: T?)
        case failure(error: V?)

        var isSuccess: Bool {

            switch self {
            case .success: return true
            case .failure: return false
            }
        }
    }

    func foo(callback: ((result: CallbackResult<Any, AnyObject>) -> Void)?) {
         callback?(result: .success(value: nil))
    }

这个解决方案很好。但就像在我的示例中一样,我们并不总是需要将任何值或错误作为参数传递。无论如何,编译器总是需要知道泛型参数应该是什么类型。因此,即使我不计量类型值是什么,我也应该至少放在那里 AnyAnyObject 。它过于复杂。

我尝试用类解决方案来改变它:

    class CallbackResult<T, V> {

        let isSuccess: Bool

        let value: T?

        let error: V?

        fileprivate init(success: Bool, value: T? = nil, error: V? = nil) {

            self.isSuccess  = success
            self.value      = value
            self.error      = error
        }

        static func success(value: T? = nil) -> CallbackResult {
            return CallbackResult(success: true, value: value)
        }

        static func failure(error: V? = nil) -> CallbackResult {
            return CallbackResult(success: false, error: error)
        }
    }

    func foo(callback: ((result: CallbackResult<Any, AnyObject>) -> Void)?) {
         callback?(result: CallbackResult.success(value: nil))
    }

它具有相同的功能。但即使这样也没有解决我的问题。你不能这样写:

CallbackResult<_, Error>

它不会起作用。

也许有人知道我的问题的解决方案?一些设置默认值的方法可能^不每次都写Any?还是目前只有丑陋的方式使用这种方法?

【问题讨论】:

    标签: ios swift generics callback


    【解决方案1】:

    Swift 3 added generic type aliases。这些可能会帮助您避免每次都输入所有类型。

    例子:

    typealias AnyResult<E> = CallbackResult<Any, E>
    typealias AnyCallback<E> = (AnyResult<E>) -> ()
    
    func foo(callback: AnyCallback<String>?) {
        callback?(.failure(error: "Ouch!"))
    }
    
    foo() { result in
        if result.isSuccess {
            // ...
        }
    }
    

    【讨论】:

    • 它部分工作。当我使用这个:typealias AnyCallback = (AnyResult) -> (),我得到一个错误'Segmentation' fault: 11
    猜你喜欢
    • 1970-01-01
    • 2018-09-12
    • 1970-01-01
    • 2017-06-20
    • 1970-01-01
    • 1970-01-01
    • 2018-02-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多