2016-09-03 108 views
0

我想註冊一個執行異步的用戶。但是,調用函數的行爲是同步的,因爲程序只應在用戶成功創建時纔會繼續。 當前的實現是:在同步調用中執行異步任務

class SignUp: NSObject { 

    // ... 

    func signUpUser() throws -> Bool { 
     guard hasEmptyFields() else { 
      throw CustomErrorCodes.EmptyField 
     } 

     guard isValidEmail() else { 
      throw CustomErrorCodes.InvalidEmail 
     } 

     createUser({ (result) in 
      guard result else { 
       throw CustomErrorCodes.UserNameTaken 
      } 
      return true // Error: cannot throw.... 
     }) 
    } 


    func createUser(succeeded: (result: Bool) ->()) -> Void { 
     let newUser = User() 
     newUser.username = username! 
     newUser.password = password! 

     // User is created asynchronously 
     createUserInBackground(newUser, onCompletion: {(succeed, error) -> Void in 
      if (error != nil) { 
       // Show error alert 
      } else { 
       succeeded(result: succeed) 
      } 
     }) 

    } 

} 

,並在視圖控制器的註冊啓動如下:

do { 
    try signup.signUpUser() 
} catch let error as CustomErrorCodes { 
    // Process error 
} 

然而,這不起作用,因爲createUser不是投擲功能。我如何才能確保signUpUser()只有在成功創建新用戶時纔會返回true?

回答

1

你說:

,並在視圖控制器的註冊啓動如下:

do { 
    try signup.signUpUser() 
} catch let error as CustomErrorCodes { 
    // Process error 
} 

但是不要。這不是異步工作。整個想法是,你不要等待。如果你在等,它不是異步的。這意味着你阻止了,而這正是你不能做的。

取而代之,安排在之後在異步過程結束時調回。那時你會聽說事情成功與否。看一個下載任務委託是如何構成的:

https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSURLSessionDownloadTask_class/

下載任務回調到委託,讓它知道我們是否成功完成。這是您想要與異步任務建立的關係。你想成爲那個代表。

+0

這是一個很好的建議。當我使用委託時,它就像一個魅力!然而,在什麼情況下使用閉包(比如對signUpUser的調用)會更好,因爲這也會使任務異步? – Taco

+0

傳遞迴調函數的好處是當你事先不知道什麼函數回調時! – matt

+0

這很有道理! – Taco

0

你需要調整你的想法。我們不需要編寫一個需要等待異步事件的同步方法,而是編寫一個採用完成閉包的方法。該方法將立即返回,但一旦異步過程完成,它將通過調用完成閉包。當你調用這樣一個方法時,你會在完成任務後調用的未完成閉包中傳入代碼。