2016-11-21 8 views
0

私は小さな未来(約束)ここthis talkに触発スウィフト3とライブラリを実装しようとしていますが、私のimplmentationです:今後の実装では、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 
      }) 
    }) 
} 

Closure use of non-escaping parameter 'completion' may allow it to escape

completion(result)とエラーの行に入る。しかし閉鎖がすでにメソッドで@escapingとしてマークされていますが、おそらくそれは、引数と戻りボイドは別の注釈を必要とするようにスウィフト3で、コードがスウィフト2

答えて

1

で働くために使用されると思われるので、それを行うために、閉鎖をとるクロージャだから[...]引数としてクロージャを取り、voidを返すクロージャが別のアノテーションを必要とするためかもしれません[...]

あなたはそうです。 Completionのタイプは(ResultType) -> Voidで、AsyncOperationファンクションタイプのパラメータであり、デフォルトではエスケープされていないことを意味します。つまり、DispatchQueue.main.asyncに渡されたようなエスケープクロージャでcompletionパラメータをキャプチャできません。

は、したがって、あなたが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あなたの質問のコードを更新してください。私は見て喜んででしょう:)また、[この要点](https://gist.github。 com/hamish knight/712de929e96966ee64760214de773caf)、私の推奨する修正が適用され、うまくコンパイルされます。 – Hamish

+0

これはフルコードhttps://gist.github.com/tunidev/17a003cd03a315440c1b2f16eed50772であり、事前に助けてくれてありがとうございます – iOSGeek

関連する問題