我正在创建一个completionHandler返回Dictionary的,但是当我在另一个类中调用此方法时,其值为nil。
completionHandler
func fetchLatestPosts(completionHandler: (responseDict: NSDictionary) -> Void in { // Bunch of JSON Parsing for dictionary to be completed var theDictionary = JSON Dictionary value responseDict = theDictionary as NSDictionary }
然后,我尝试在另一个类中调用它,以便fetchLatestPost可以查看Dictionary 的值并基于该值显示数据。例如,
fetchLatestPost
func parseDictionary() { NetworkManager.sharedInstance.fetchLatestPosts(responseDict: NSDictionary) if (responseDict != nil) { println("Dictionary is not empty") }
这里的问题是,当我调用fetchLatestPosts函数时,我nil在尝试调用字典时收到一个值。
fetchLatestPosts
nil
简而言之,我的问题是如何为完成处理程序分配值并在Xcode项目中的其他位置调用它?
您的问题很乱。您的示例代码无效,并且没有显示正在使用的完成处理程序。
我怀疑您误解了异步请求和完成处理程序的工作方式。这是顺序。
这是一个具有完成处理程序的异步过程如何工作的实际示例:(您可以在 此链接 上找到一个工作的Xcode项目,该项目在Github上演示了此代码)
首先是一个AsyncManager类,它模拟从互联网下载图像:
class AsyncManager { static let sharedAsyncManager = AsyncManager() func asyncFetchImage(#imageName: String, completion: (image: UIImage?, status: String) -> ()) { println("Entering \(__FUNCTION__)") //Simulate a network operation by waiting 3 seconds before loading an image let nSecDispatchTime = dispatch_time(DISPATCH_TIME_NOW, Int64(3.0 * Double(NSEC_PER_SEC))) let queue = dispatch_get_main_queue() dispatch_after(nSecDispatchTime, queue) { () -> Void in let result = UIImage(named: imageName) println("Loading image in background") let status = result != nil ? "image loaded" : "Error loading image" println("About to call completion handler") completion(image: result, status: status) } println("Leaving \(__FUNCTION__)") } }
这是一个单身人士。它具有一个静态let sharedAsyncManager,可用于获取AsyncManager的单个实例。
AsyncManager提供了一个方法asyncFetchImage,该方法带有一个图像名称和一个完成块。该函数不会返回任何结果,因为它会在图像加载之前立即返回。
该代码并没有真正从互联网上下载图像。取而代之的是,它仅使用GCD调用dispatch_after来等待3秒钟,然后加载图像并调用完成块。
现在,我创建一个ViewController类,并给它一个“加载图像”按钮。我创建了IBOutlet theImageView一个UIImageView,以显示要加载的图像。
IBOutlet
theImageView
UIImageView
我为“加载图像”按钮编写了IBAction方法。这是IBAction的样子:
@IBAction func loadImage(sender: UIButton) { let theAsyncManager = AsyncManager.sharedAsyncManager println("about to call asyncFetchImage") theAsyncManager.asyncFetchImage(imageName: "wareto_blue_150x115") { (image, status) -> () in println("Beginning completion block") self.theImageView.image = image println("In completion block, status = \(status)") } println("After call to asyncFetchImage") } }
现在,有趣的部分。这是事件的顺序:
我按下loadImage按钮。IBAction方法运行。
它获得了对异步下载管理器单例的引用。
它显示一条消息,然后调用theAsyncManager.asyncFetchImage。AsyncManager.asyncFetchImage方法在输入时显示一条消息,在3秒钟后排队调用以加载图像,显示“ leaving”消息, 然后在加载图像之前 返回。没有返回任何内容,因为图像加载代码尚未运行。
视图控制器的loadImage方法显示其“调用asyncFetchImage之后”消息并返回。
几秒钟后,asyncFetchImage内部的代码实际上开始运行。它显示一条消息,加载图像,然后调用完成处理程序。
这是您在运行上述代码时返回的一组消息:
about to call asyncFetchImage Entering asyncFetchImage(imageName:completion:) Leaving asyncFetchImage(imageName:completion:) After call to asyncFetchImage Loading image in background About to call completion handler Beginning completion block In completion block, status = image loaded
请注意,loadImage IBAction的最后一行:
println("After call to asyncFetchImage")
在显示有关加载图像的消息之前显示一条消息。在完成任何工作之前,对asyncFetchImage的代码调用将立即返回。调用asyncFetchImage之后的代码将继续运行,但该图像仍未加载。此时无法返回结果,因为图像加载尚未开始。