在Swift

时间:2016-01-05 09:42:35

标签: ios iphone swift dictionary

我在此集合视图详细信息视图代码中收到上述错误。

Detail VC

class DetailViewController: UIViewController {

    @IBOutlet weak var imageView: UIImageView?

    var photo: NSDictionary?

    var image1:UIImage = UIImage()

    override func viewDidLoad() {

    super.viewDidLoad()

    // Do any additional setup after loading the view.
    //downloadFromUrl(url)
    if let photo = photo {
        let url1 = (photo["images"]!["thumbnail"]!!["url"])! as! String
        let url:NSURL = NSURL(string: url1 as String)!
        //print(url)
        downloadFromUrl(url)
    }


}


      func downloadFromUrl(url: NSURL) {
    //self.imageView.hnk_setImageFromURL(url)
    let config:NSURLSessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()
    let session:NSURLSession = NSURLSession(configuration: config)
    let request:NSURLRequest = NSURLRequest(URL: url)
    let task = session.downloadTaskWithRequest(request) { (location, response, error) -> Void in

        let data:NSData = NSData(contentsOfURL: location!)!
        let image:UIImage = UIImage(data: data)!

        dispatch_async(dispatch_get_main_queue(), { () -> Void in

                self.image1 = image
                print(self.image1)

                self.imageView.image = self.image1

        })
    }


    task.resume()


}        

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

以下是collection VC中的一些方法:

override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! PhotosViewCell

    cell.backgroundColor = UIColor.brownColor()

    cell.photo = self.photos[indexPath.row] as? NSDictionary

    //self.p = self.photos[indexPath.row] as! NSDictionary
    //print("Link is \(cell.photo!["link"]!)")

    return cell
}

override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {

    let p = self.photos[indexPath.row] as! NSDictionary
    let VC:DetailViewController = DetailViewController()
    VC.photo = p

    self.presentViewController(VC, animated: true, completion: nil)
}

我知道我可能会收到此错误,因为 viewDidLoad() 尚未准备好但是解决方案是什么,我确实需要 viewDidLoad() 因为我需要调用 downloadFromUrl() 方法。

哦,我没有使用 prepareforsegue() 方法。也尝试过,也许我做错了。 在调试区域,我得到以下内容:

 2016-01-06 13:30:55.075 AuthCheck[3623:74910] Warning: Attempt to present    <AuthCheck.DetailViewController: 0x7ff103dfb6c0> on <AuthCheck.PhotosViewController: 0x7ff103c2fd90> whose view is not in the window  hierarchy!
  <UIImage: 0x7ff103cd1820>, {150, 150}
  fatal error: unexpectedly found nil while unwrapping an Optional value

这意味着正在下载正确的图像,但无法将其设置为imageView的图像属性。不明白为什么? 有人会告诉我解决方案吗?

3 个答案:

答案 0 :(得分:0)

您收到运行时错误,因为您强行解包一个恰好不包含任何值的可选项(即nil)。在打开之前请检查您的选项(这是一个好习惯):

print(photo!) // <--Dangerous

if let photo = photo {
    print(photo) // <--Safe
}

...除非您的代码路径使其100%确定可选的 包含值。

您正在从互联网上下载数据;这通常应该是异步操作,因为它需要很长时间,并且您不想在完成时冻结主线程(用户界面)。 所以你需要在后台执行它,并在完成处理程序中使用获得的数据(即阻塞或关闭)。

答案 1 :(得分:0)

加载视图控制器时会调用

ViewDidLoad(),这意味着在您呈现视图控制器之前创建实例时会发生

// viewDidLoad() is called right here
let VC:DetailViewController = DetailViewController()
// this happens after you try to print photo
VC.photo = p

这意味着您的可选变量photo在打印时仍为null。为避免错误,您可以使用

解包变量
if let photo = photo {
    print(photo)
}

虽然这不会帮助你实现目标。因此,viewDidAppear而不是viewDidLoad执行您的任务,在视图变为可见后调用。

override func viewDidAppear() {
    super.viewDidAppear()

    print(photo!)
    downloadFromUrl(url)
}

或者,如果您需要在视图出现之前执行任务,DetailViewController中创建一个单独的函数,并在分配VC.photo后调用它。

func task() {
    print(photo!)
    downloadFromUrl(url)
}

然后在CollectionView中,执行

let p = self.photos[indexPath.row] as! NSDictionary
let VC:DetailViewController = DetailViewController()
VC.photo = p
VC.task()

答案 2 :(得分:0)

实际上更安全的方法是从didSet方法调用downloadFromUrl(url),如下所示:

var photo: NSDictionary = NSDictionary() { 
   didSet {
       // your code to get the url here you can test if photo is nil
       downloadFromUrl(url)
   }
}

但这不是问题所在。由于您没有使用故事板来初始化您的viewController(让VC = DetailViewController()),您永远不会实例化您的viewController的内容(例如imageView)