Search code examples
swiftswift3segueuistoryboardsegue

attempt to perform segue leads to "terminating with uncaught exception of type NSException"


I have a UITableView VC for which the cells are linked to the prepare for segue function and this works. it moves to the correct VC. I have added the rightBarButtonItem on the navigation item which I linked to a method that calls the performForSegue and I give it the correct identifier. It all runs fine until i click the right side button. When I do i get a: "First throw call stack. terminating with uncaught exception of type NSException" Could someone please help me and point me in the right direction please? Code and print listing below. Thank you.

class AssignNumberOfRoomsForFloorsVC: UITableViewController {

//MARK: - Properties

private var managedObjectContext: NSManagedObjectContext!

private var storedFloors = [Floors]()


//MARK: - Actions

override func viewDidLoad() {
    super.viewDidLoad()
    managedObjectContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
    loadFloorData()
    self.tableView.reloadData()
    self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.done, target: self, action: Selector(("navigateToNextViewController")))

}

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

private func loadFloorData() {
    let request: NSFetchRequest<Floors> = Floors.fetchRequest()
    request.returnsObjectsAsFaults = false
    do {
        storedFloors = try managedObjectContext.fetch(request)
    }
    catch {
        print("could not load data from core \(error.localizedDescription)")
    }
}

private func navigateToNextViewController(){
    self.performSegue(withIdentifier: "room and alarm type", sender: self)
}



// MARK: - Table view data source

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

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

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "floor cell", for: indexPath) as! FloorCell
    let floorItem = storedFloors[indexPath.row]
    cell.floorNumberTxt.text = String(floorItem.floorNumber)
    return cell
}

// MARK: - Navigation

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    var selectedRow = self.tableView.indexPathForSelectedRow
    let floorItem = storedFloors[(selectedRow?.row)!]
    let destinationController = segue.destination
    if let assignRoomsVC = destinationController as? DeclareRoomsVC {
        if let identifier = segue.identifier {
            switch identifier {
            case "assign number of rooms":
                let _ = assignRoomsVC.view
                assignRoomsVC.floorNumberTxt.text = String(floorItem.floorNumber)
                assignRoomsVC.selectedFloor = floorItem.floorNumber
            default: break
            }
        }
    }
}

}

This is the message in the console:

2017-03-26 21:50:28.041 PDCiPad[10433:292572] -[PDCiPad.AssignNumberOfRoomsForFloorsVC navigateToNextViewController]: unrecognized selector sent to instance 0x7ff5b7c326c0

2017-03-26 21:50:28.219 PDCiPad[10433:292572] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[PDCiPad.AssignNumberOfRoomsForFloorsVC navigateToNextViewController]: unrecognized selector sent to instance 0x7ff5b7c326c0' * First throw call stack: ( 0 CoreFoundation 0x000000010db79d4b exceptionPreprocess + 171 1 libobjc.A.dylib 0x000000010d1ba21e objc_exception_throw + 48 2 CoreFoundation 0x000000010dbe9f04 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132 3 CoreFoundation 0x000000010daff005 ___forwarding_ + 1013 4 CoreFoundation 0x000000010dafeb88 _CF_forwarding_prep_0 + 120 5 UIKit 0x000000010e6b28bc -[UIApplication sendAction:to:from:forEvent:] + 83 6 UIKit 0x000000010eaf44a1 -[UIBarButtonItem(UIInternal) _sendAction:withEvent:] + 149 7 UIKit 0x000000010e6b28bc -[UIApplication sendAction:to:from:forEvent:] + 83 8 UIKit 0x000000010e838c38 -[UIControl sendAction:to:forEvent:] + 67 9 UIKit 0x000000010e838f51 -[UIControl _sendActionsForEvents:withEvent:] + 444 10 UIKit 0x000000010e8390db -[UIControl _sendActionsForEvents:withEvent:] + 838 11 UIKit 0x000000010e837e4d -[UIControl touchesEnded:withEvent:] + 668 12 UIKit 0x000000010e720545 -[UIWindow _sendTouchesForEvent:] + 2747 13 UIKit 0x000000010e721c33 -[UIWindow sendEvent:] + 4011 14 UIKit 0x000000010e6ce9ab -[UIApplication sendEvent:] + 371 15 UIKit 0x000000010eebb72d dispatchPreprocessedEventFromEventQueue + 3248 16 UIKit 0x000000010eeb4463 __handleEventQueue + 4879 17 CoreFoundation 0x000000010db1e761 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION + 17 18 CoreFoundation 0x000000010db0398c __CFRunLoopDoSources0 + 556 19 CoreFoundation 0x000000010db02e76 __CFRunLoopRun + 918 20 CoreFoundation 0x000000010db02884 CFRunLoopRunSpecific + 420 21 GraphicsServices 0x0000000113908a6f GSEventRunModal + 161 22 UIKit 0x000000010e6b0c68 UIApplicationMain + 159 23 PDCiPad 0x000000010cad8c1f main + 111 24 libdyld.dylib 0x0000000111a3268d start + 1 ) libc++abi.dylib: terminating with uncaught exception of type NSException

new problem


Solution

  • When you click on your UIBarButtonItem, selectedRow is nil because you use indexPathForSelectedRow and you didn't select any row.

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) is called if you click on your UIBarButtonItem or a tableView cell.

    So it work when you click on your tableView cell because self.tableView.indexPathForSelectedRow will return the index of the selected cell. But will return nil for your UIBarButtonItem.

    Finally, if you use a ! on a nil value you crash.