dispatch_async中的完成处理程序错误 - 可选的展开

时间:2015-10-17 14:12:40

标签: ios swift

我遵循了一个使用Dribbble API实现获取数据的教程 我被困在完成处理程序错误上 我确认shots正确地将元素作为NSDictionary类型 这是由并发队列的竞争条件引起的吗? 先感谢您。

DribbbleAPI.swift

//
//  DribbbleAPI.swift
//  iShots
//
//  Created by Seo Yoochan on 10/15/15.
//  Copyright © 2015 yoochan. All rights reserved.
//

import Foundation


class DribbbleAPI {
    let accessToken = "6d23de112fd5859e7d5658e6b41eee5f1e76291e3327882017457352c56e61a9"

    func loadShots(completion: ((AnyObject) -> Void)!) {
        let url = "https://api.dribbble.com/v1/shots?access_token=" + accessToken

        let session = NSURLSession.sharedSession()
        let shotsURL = NSURL(string: url)

        let task = session.dataTaskWithURL(shotsURL!) {
            (data, resposne, error) -> Void in

            if error != nil {
              print(error!.localizedDescription)
            } else {

                do {

                    let shotsData = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers)


                    var shots = [Shot]()

                    for shot in shotsData as! NSArray {
                        let shot = Shot(data: shot as! NSDictionary)
                        shots.append(shot)

                    }

                    if shots.count > 0 {
                        dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_USER_INITIATED.rawValue), 0)){

                            dispatch_async(dispatch_get_main_queue()){
                                completion(shots) // error here
                            }
                        }
                    }




                } catch {
                }
            }
        }

        task.resume()


    }


}

Shot.swift

//
//  Shot.swift
//  iShots
//
//  Created by Seo Yoochan on 10/15/15.
//  Copyright © 2015 yoochan. All rights reserved.
//

import Foundation

class Shot {
    var id: Int!
    var title: String!
    var description: String!
    var commentCount: Int!
    var likesCount: Int!
    var viewsCount: Int!
    var commentUrl: String!
    var imageUrl: String!
    var imageData: NSData?

    init(data: NSDictionary){
        self.id = data["id"] as! Int
        self.commentCount = data["comments_count"] as! Int
        self.likesCount = data["likes_count"] as! Int
        self.viewsCount = data["views_count"] as! Int
        self.commentUrl = getStringFromJSON(data, key: "comments_url")
        self.title = getStringFromJSON(data, key: "title")
        self.description = getStringFromJSON(data, key: "description")
        let images = data["images"] as! NSDictionary
        self.imageUrl = getStringFromJSON(images, key: "normal")


    }

    func getStringFromJSON(data: NSDictionary, key: String) -> String {

        if let info = data[key] as? String {
           return info
        }

        return ""
    }
}

ViewController.swift

//
//  ViewController.swift
//  iShots
//
//  Created by Seo Yoochan on 10/15/15.
//  Copyright © 2015 yoochan. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        let api = DribbbleAPI()
        api.loadShots(nil)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

错误日志

fatal error: unexpectedly found nil while unwrapping an Optional value

1 个答案:

答案 0 :(得分:1)

您可以通过<?= $this->Time->format($event->date, [null, \IntlDateFormatter::SHORT]) ?> 调用您的方法,然后在该方法中调用您的api.loadShots(nil),如果completion(shots)定义为completion ((AnyObject) -> Void)!,这当然不起作用}。

您可能希望将该代码更改为

nil

甚至更短一点

func loadShots(completion: ((AnyObject) -> Void)?) {
    ...
    if let callback = completion {
        callback(shots)
    }
    ...
}

如果您希望编码器始终必须提供如下所示的回调,请另外删除所有可选项。请注意,在这种情况下,编译器不允许传递nil。

completion?(shots)

你目前在你的代码中使用的是一个隐含的未包装的可选项,这基本上意味着它可以不时地保持nil但是如果它需要自动解包它会这样做,如果值不是nil将会起作用。使用隐含的无包装选项会导致开发人员(您)必须更加小心,或者发生崩溃等事情。

您可能希望再次read up on optionals