我在此集合视图详细信息视图代码中收到上述错误。
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的图像属性。不明白为什么? 有人会告诉我解决方案吗?
答案 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)