Miles
Miles

Reputation: 625

Error in Swift 3 update - Unexpectedly found nil while unwrapping an optional value

I'm trying to segue an image from a "tableview controller" into a separate view where the image can be viewed "full-screen". The code I was using worked great until I updated to Swift 3. I've been reading about unwrapping optional values and I can't figure out what the error is here.

Thanks!

The line of code that the error is on:

    Detailimageview.sd_setImage(with: URL(string:self.sentData1))

ERROR: fatal error: unexpectedly found nil while unwrapping an Optional value

The "full-screen" view controller in which this error is happening:

import UIKit

class PhotoView: UIViewController, UIPopoverPresentationControllerDelegate, UIScrollViewDelegate {

@IBOutlet weak var containerView: UIView!

@IBOutlet weak var scrollView: UIScrollView!

@IBOutlet weak var Detailimageview: UIImageView!


var sentData1:String!


func scrollViewDidZoom(_ scrollView: UIScrollView) {
    let imageViewSize = Detailimageview.frame.size
    let scrollViewSize = scrollView.bounds.size

    let verticalPadding = imageViewSize.height < scrollViewSize.height ? (scrollViewSize.height - imageViewSize.height) / 2 : 0
    let horizontalPadding = imageViewSize.width < scrollViewSize.width ? (scrollViewSize.width - imageViewSize.width) / 2 : 0

    scrollView.contentInset = UIEdgeInsets(top: verticalPadding, left: horizontalPadding, bottom: verticalPadding, right: horizontalPadding)
}

func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
    return Detailimageview
}

func setZoomScale() {
    let imageViewSize = Detailimageview.bounds.size
    let scrollViewSize = scrollView.bounds.size
    let widthScale = scrollViewSize.width / imageViewSize.width
    let heightScale = scrollViewSize.height / imageViewSize.height

    scrollView.minimumZoomScale = min(widthScale, heightScale)
    scrollView.zoomScale = 1.0


}

override func viewWillLayoutSubviews() {
    setZoomScale()
}

override func viewDidLoad() {
    super.viewDidLoad()


    Detailimageview.sd_setImage(with: URL(string:self.sentData1))


    // Do any additional setup after loading the view.

    setZoomScale()
}

 func prepare(for segue: UIStoryboardSegue, sender: AnyObject?) {


}


func viewForZooming(in scrollView: UIScrollView) -> UIView? {
    return containerView

}

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

@IBAction func DismissView(_ sender: AnyObject) {

    self.dismiss(animated: true, completion: nil)
}

@IBAction func showPopup(_ sender: AnyObject) {

    let popOverVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "sbPopUpID") as! PopUpViewController
    self.addChildViewController(popOverVC)
    popOverVC.view.frame = self.view.frame
    self.view.addSubview(popOverVC.view)
    popOverVC.didMove(toParentViewController: self)
}

override var prefersStatusBarHidden: Bool {
    get {
        return true
    }
}

The "tableview controller":

import UIKit

class ListViewController: UITableViewController {

var imageURLs = [String]()




let cellVenue = ["Example Venue","Example Venue1","Example Venue2","Example Venue3","Example Venue4","Example Venue5"]

let cellLocation = ["Example Venue, Location","Example Venue, Location1","Example Venue, Location2","Example Venue, Location3","Example Venue, Location4","Example Venue, Location5"]

let cellDate = ["Example Date, 1970","Example Date, 1971","Example Date, 1972","Example Date, 1973","Example Date, 1974","January 1st, 1975"]



override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

}

override func viewDidLoad() {
    super.viewDidLoad()


    imageURLs = ["https://i.imgur.com/bSfVe7l.jpg","https://i.imgur.com/vRhhNFj.jpg","https://i.imgur.com/bSfVe7l.jpg","https://i.imgur.com/vRhhNFj.jpg","https://i.imgur.com/bSfVe7l.jpg"]

    self.tableView.separatorStyle = .none

    // tableView.indicatorStyle = UIScrollViewIndicatorStyle.white

    self.view.backgroundColor = UIColor.black

    self.navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white]

    navigationController!.navigationBar.barTintColor = UIColor.black




}



override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}


override func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
   return imageURLs.count

}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell: ListViewCell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! ListViewCell

    let imageView = cell.viewWithTag(1) as! UIImageView

    imageView.sd_setImage(with: URL(string: imageURLs[indexPath.row]))

    imageView.sd_setHighlightedImage(with: URL(string: imageURLs[indexPath.row]), options: [.continueInBackground, .progressiveDownload, .avoidAutoSetImage])

    cell.cellVenue.text = cellVenue[indexPath.row]

    cell.cellLocation.text = cellLocation[indexPath.row]

    cell.cellDate.text = cellDate[indexPath.row]


    return cell

}

 func prepare(for segue: UIStoryboardSegue, sender: AnyObject?) {


    if (segue.identifier == "DetailView")  {
        // segue.destination is correct, xcode keeps switching it to segue.description
        let VC = segue.destination as! PhotoView
        if let indexpath = self.tableView.indexPathForSelectedRow {

            let Imageview = imageURLs[indexpath.row] as String
            VC.sentData1 = Imageview
        }
    }



}

override var prefersStatusBarHidden: Bool {
    get {
        return true
    }
}

Upvotes: 0

Views: 781

Answers (1)

Dima
Dima

Reputation: 23624

It looks like this is a view lifecycle issue. viewDidLoad on the child controller is getting called before prepareForSegue is called or at least before it is completed on the parent. Looking around I see conflicting info on whether this is supposed to happen and I don't typically use storyboards so I'm not positive myself. In any case, an easy fix in your case is just to move your image setting code out of viewDidLoad and into viewWillAppear. The URL should definitely be set by that point and your optional will be unwrapped successfully.

Upvotes: 2

Related Questions