2016-09-14 3 views
2

Я пытаюсь реализовать какое-то одно решение для каждого обратного вызова в приложении. Поэтому я хочу, чтобы любой обратный вызов использовал один класс или, по крайней мере, семейство классов.Swift generics со значением по умолчанию

  • Каждый обратный вызов может быть успешным или нет.
  • Если он успешный, он может содержать некоторые результаты операции.
  • Если это не так, он может содержать информацию о том, что не удалось.

Распространенное использование обратных вызовов выглядит следующим образом:

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

Или:

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

мне не нравится ни один из них. Я хочу иметь одно элегантное решение для каждого обратного вызова. Я нашел что-то подобное в библиотеке Alamofire.

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

Это решение это приятно. Но, как и в моем примере, нам не всегда нужно передавать любое значение или ошибку в качестве параметра. В любом случае, компилятор всегда должен знать, с какими должны быть общие параметры. Поэтому, даже если я не измеряю значение типа, я всегда должен положить туда по крайней мере Any или AnyObject. Это сложно.

Я попытался изменить его с помощью класса решения:

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 каждый раз? Или на данный момент существует только уродливый способ использования этого подхода?

ответ

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 { 
     // ... 
    } 
} 
+0

Он работает частично. Когда я использую это: typealias AnyCallback = (AnyResult ) ->(), я получаю сообщение об ошибке «Сегментация»: 11 –

Смежные вопросы