简体   繁体   中英

Swift Protocols - Delegate Is Nil, Causing Crash - NOT About Optionals

Edit: Please read carefully. Everyone who has tried to help thinks I am asking about why a nil unwrapped optional causes a crash. I am not. I am trying to determine why it was nil in the first place. And thanks to those who have tried to help! I do appreciate it.

Newbie question. I am building a weather forecast app as part of learning to program in Swift.

I have a protocol for passing a location back to my main forecast class to use to return a forecast for a certain location. I have two different classed that use the protocol when returning a location to return a forecast for.

I was having an issue that one of the classes would cause a crash for unwrapping a nil with regard to delegate to the forecast class. The other class, set up with exactly the same return function did not have this error. I tracked the crash down to the prepare(for segue: function in the forecast class. Because I did not need t pass information forward to one of the classes, I did not set destinationViewController.delegate = self for the class that crashed. My question is simply why did I have to set that in the forecast class in order to prevent the unwrapping a nil crash.

I know I missed something in why a protocol has to be set up this way, but I can't seem to find the answer as to why. I wanted to ask this question for me, and for others to find when this crash occurs.

I think this post addresses my issue, but does not answer the "why," just the "what." What does setting the destinationVC.delegate = self in the class that initiates the segue do that setting weak var delegate: ForecastTableViewController! does not?

Thanks.

My code is as follows:

ForecastTableViewController class:

class ForecastTableViewController: UITableViewController, CLLocationManagerDelegate, LocationToForecast {

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

    getLocationNameAndStoreLocation(latitude: (self.weatherData.locationCoordinates.latitude), longitude: (self.weatherData.locationCoordinates.longitude))

    if segue.identifier == "locationViewSegue", let destinationViewController = segue.destination as? LocationViewController  {
        destinationViewController.delegate = self
        destinationViewController.weatherData = self.weatherData
        destinationViewController.wxObservationStationsArray = self.wxObservationStationsArray
        destinationViewController.newCoordinates = self.weatherData.locationCoordinates
    } else if segue.identifier == "searchPriorLocations", let destinationViewController = segue.destination as? SearchBarTableViewController  {
        destinationViewController.delegate = self
    }
}

LocationViewController class:

class LocationViewController: UIViewController, CLLocationManagerDelegate, UIGestureRecognizerDelegate, UIPickerViewDataSource, UIPickerViewDelegate {

    weak var delegate: ForecastTableViewController!


   override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(true)

    switch coordinateChoice {
    case currentLocationTrue: newCoordinates = currentLocation
    case UIPickerTrue:

        newCoordinates = UIPickerLocation

    case longPressTrue: newCoordinates = longPressLocation
    default: break
    }

    self.delegate!.returnLocationToForecast(locationToReturn: newCoordinates)
    performSegueToReturnBack()
}

SearchBarTableViewController class:

class SearchBarTableViewController: UITableViewController, UISearchResultsUpdating, NSFetchedResultsControllerDelegate {

    weak var delegate: ForecastTableViewController!


   override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(true)

    if !(newCoordinates.latitude == 0 && newCoordinates.longitude == 0) {
        self.delegate!.returnLocationToForecast(locationToReturn: newCoordinates)
    }

    performSegueToReturnBack()
}

My question is simply why did I have to set that in the forecast class in order to prevent the unwrapping a nil crash

Because you said self.delegate! . That means "crash me if I have no delegate." You cannot complain if Swift does exactly what you said to do !

If you don't want to crash, then don't say that . Say self.delegate? instead.

try with AnyObject instead of class . in some cases it may crash if we use class in non class object .

protocol DemoDelegate : AnyObject {   
}

class DemoViewController: UIViewController 
{

weak var delegate : DemoDelegate?

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM