2016-11-21 3 views
0

Я пытаюсь реализовать небольшое будущее (обещания) библиотека с Swift 3 вдохновлен this talk здесь мой implmentation:реализация Будущее в Swift 3

public enum Result<T, E: Error> { 
    case Success(T) 
    case Error(E) 
} 

public struct Future<T, E: Error> { 
    public typealias ResultType = Result<T, E> 
    public typealias Completion = (ResultType) -> Void 
    public typealias AsyncOperation = (Completion) -> Void 

    private let operation: AsyncOperation 

    public init(result: ResultType) { 
     self.init(operation: { completion in 
      completion(result) 
     }) 
    } 

    public init(value: T) { 
     self.init(result: .Success(value)) 
    } 

    public init(error: E) { 
     self.init(result: .Error(error)) 
    } 
    public init(operation: @escaping (Completion) -> Void) { 
     self.operation = operation 
    } 

    public func start(completion: Completion) { 
     self.operation() { result in 
      completion(result) 
     } 
    } 
} 

//: ### Error handeling 

enum UserInfoErrorDomain: Error { 
    case UserDoesNotExist 
    case UserRequestFailure 
    case NetworkRequestFailure 
} 

и вот мое использование:

func downloadFile(URL: NSURL) -> Future<NSData, UserInfoErrorDomain> { 

    return Future(operation: { completion in 
      DispatchQueue.main.async(execute: { 
       print("Async2") 
       let result: Result<NSData, UserInfoErrorDomain> 

       if let data = NSData(contentsOf: URL as URL) { 
        result = Result.Success(data) 
       } 
       else { 
        result = Result.Error(.NetworkRequestFailure) 
       } 

       completion(result) // ERROR here Closure use of non-escaping parameter 'completion' may allow it to escape 
      }) 
    }) 
} 

, но я получаю в строке completion(result) и ошибки Closure use of non-escaping parameter 'completion' may allow it to escape

но закрытие уже отмечен как @escaping в методе public init(operation: @escaping (Completion) -> Void) но, возможно, потому, что это замыкание, который принимает замыкание в качестве аргумента и возвращает недействительные нужна другая аннотация, так, чтобы сделать это в Swift 3, потому что кажется, что код, используемый для работы в Swift 2

ответ

1

[...] но возможно потому, что это замыкание, которое принимает замыкание в качестве аргумента и возвращает void нуждается в другой аннотации [...]

Вы правы. Completion имеет тип (ResultType) -> Void, который, поскольку он является параметром вашего типа AsyncOperation, означает, что он не выполняет экранирование по умолчанию - это означает, что вы не можете зафиксировать свой параметр completion в экранирующем закрытии (например, один прошел до DispatchQueue.main.async).

Поэтому вам нужно аннотировать Completion в @escaping:

public typealias AsyncOperation = (@escaping Completion) -> Void 

, и вы хотите, чтобы ваши init(operation:) и start(completion:) функции выглядеть следующим образом:

public init(operation: @escaping AsyncOperation) { 
    self.operation = operation 
} 

// the completion: parameter needs to be escaping as it's going to be called after 
// an async operation has completed. 
public func start(completion: @escaping Completion) { 
    self.operation { result in 
     completion(result) 
    } 
} 
+0

Спасибо за ваш ответ, я попытался ваше предложение, но у меня такое же предупреждение – iOSGeek

+0

@iOSGeek Пожалуйста, обновите код в своем вопросе, и я с удовольствием посмотрю :) Вы также можете взглянуть на [этот gist] (https: //gist.github. ком/хамит knight/712de929e96966ee64760214de773caf) с моими исправлениями, которые компилируются отлично. – Hamish

+0

это полный код https://gist.github.com/tunidev/17a003cd03a315440c1b2f16eed50772 и спасибо за помощь заранее – iOSGeek

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