Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Crash when setting navigation items on UINavigationBar

I have a view controller which is embedded in a navigation controller.

On the navigation bar, I have a segmentedControl in the centre of the bar, and then an edit button to the right.

When I tap the Edit button, the following code is fired:

func editAction() {

    if homeworkTasksVC?.editing == false {

        // Set to editing
        homeworkTasksVC?.setEditing(true, animated: true)

        // Switch to "Done" button and 'Homework' title without segmented control
        let navBar = self.navigationController?.navigationBar
        let navItem = UINavigationItem(title: "Homework")

        let doneButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Done, target: self, action: #selector(TasksParentViewController.editAction))
        navItem.rightBarButtonItem = doneButton

        navBar!.setItems([navItem], animated: true)


    } else {

        // Stop editing
        homeworkTasksVC?.setEditing(false, animated: true)

        // Switch back to "Edit" button and segmented control
        let navBar = self.navigationController?.navigationBar
        let navItem = UINavigationItem(title: "Homework")
        navItem.titleView = segmentControl

        let editButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Edit, target: self, action: #selector(TasksParentViewController.editAction))
        navItem.rightBarButtonItem = editButton

        navBar!.setItems([navItem], animated: true)

    }

}

(Note: the homeworkTasksVC is referenced because the view in question is a UIPageViewController than switches between two views)

PROBLEM: When I tap edit, the segmented control switches for the text title without any issue, and then switches back all fine when tapping "Edit" again, BUT if I tap a cell in the view which navigates to a different view, and then tap 'back' to get back to this original view, and THEN tap edit, it crashes with the following output:

2016-06-22 00:38:59.272 2.0[1504:386949] * Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Cannot call setItems:animated: directly on a UINavigationBar managed by a controller.' * First throw call stack: (0x23c85b0b 0x23442dff 0x23c85a51 0x283a0ced 0x118318 0x1189c8 0x2829b6a1 0x2841e0b9 0x2829b6a1 0x2829b631 0x2828356b 0x28283697 0x2829af51 0x2829abbf 0x28293547 0x28263dd5 0x28262379 0x23c479e7 0x23c475d7 0x23c4593f 0x23b941c9 0x23b93fbd 0x251b0af9 0x282cc435 0xe8cb4 0x23840873) libc++abi.dylib: terminating with uncaught exception of type NSException (lldb)

like image 448
Max Avatar asked Jun 21 '16 14:06

Max


2 Answers

What you want is to set the navigationItem property on the current view controller. When you push a second view controller on the navigation stack, UINavigationController takes over management of the nav bar items. It might actually be a bug that it works before the push.

Instead of:

navBar!.setItems([navItem], animated: true)

do either:

homeworkTasksVC.navigationItem = navItem

or:

self.navigationItem = navItem

Which one to pick depends on how you're stacking your view controllers.

like image 138
robinkunde Avatar answered Nov 17 '22 07:11

robinkunde


As Chuck Krutsinger said, now navigationItem is a get only property. Your code must be:

homeworkTasksVC.navigationBar.topItem?.rightBarButtonItem = editButton
like image 1
Danilo Lombardi Avatar answered Nov 17 '22 05:11

Danilo Lombardi