我遵循了一个使用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
您通过api.loadShots(nil)
调用您的方法,然后在该方法中编写completion(shots)
,如果completion
定义为((AnyObject) -> Void)!
是nil
,这当然不会起作用。
你可能想把代码改成
func loadShots(completion: ((AnyObject) -> Void)?) {
...
if let callback = completion {
callback(shots)
}
...
}
或者更短一点的
completion?(shots)
或者,如果您希望编码器总是必须提供如下所示的回调,则将可选的全部删除。注意,在这种情况下,编译器将不允许传递nil。
func loadShots(completion: ((AnyObject) -> Void)) {
...
completion(shots)
...
}
你目前在你的代码中使用的是一个隐式unwrapped可选的,这基本上意味着它可以保持nil不时,但如果它需要被解封,它会自动这样做,这将只工作,如果值不是nil。使用隐式展开可选选项会导致开发人员(您)必须更加小心,否则会发生类似崩溃的事情。
你可能需要再次阅读可选选项