微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在completionHandlers中存储值 – Swift

我正在创建一个completionHandler,它返回一个Dictionary但是当我在另一个类中调用这个方法时,它的值是nil.

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的值并根据该值显示数据.
例如,

func parseDictionary() {
NetworkManager.sharedInstance.fetchLatestPosts(responseDict: NSDictionary)
if (responseDict != nil) {
println("Dictionary is not empty")
}

这里的问题是,当我调用fetchLatestPosts函数时,我在尝试调用Dictionary时收到一个nil值.

简而言之,我的问题是我如何分配存储的完成处理程序的值,并可以在Xcode项目的其他地方调用

解决方法

你的问题是乱码.您的示例代码无效,并且未显示正在使用的完成处理程序.

我怀疑你误解了异步请求和完成处理程序的工作原理.这是序列.

>调用函数并提供完成处理程序
>函数立即返回,并在将来生命运行请求中
>完成处理程序之后的下一行在请求开始处理之前运行.您的应用继续运行.没有结果,因为请求尚未完成.
>异步请求终于完成了.原始方法调用完成处理程序.现在结果可用,在完成处理程序的代码中.完成处理程序代码执行处理结果所需的任何操作.

下面是一个关于完成处理程序的异步过程如何工作的现实示例:(您可以在this link找到一个在Github上演示此代码的有效Xcode项目)

首先是模拟从互联网下载图像的类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,它将显示我要加载的图像.

我为“加载图像”按钮编写了一个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方法运行.

它获得了对异步下载管理器单例的引用.

显示一条消息,然后调用AsyncManager.asyncFetchImage. AsyncManager.asyncFetchImage方法在输入时显示消息,在3秒后对调用进行排队以加载图像,显示“离开”消息,并在加载图像之前返回.没有什么可以返回,因为图像加载代码还没有运行.

视图控制器的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之后的代码会运行,但图像仍未加载.此时无法返回结果,因为图像负载尚未开始.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐