Reputation: 43
I am trying to create a simple contact list app as an avenue of learning Swift. Unfortunately no matter what I try I cannot have my contacts' details display into an editable text field on a different view controller to the tableview (which contains the main contacts).
Here is the block of code that should be effecting the text fields (i am unsure of what other code to supply)
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showDetail" {
if let indexPath = self.tableView.indexPathForSelectedRow {
let object = objects[indexPath.row]
let controller = (segue.destinationViewController as! UINavigationController).topViewController as! DetailViewController
print(object.firstName)
controller.fiName?.text = object.firstName
controller.laName?.text = object.lastName
controller.miName?.text = object.middleName
controller.aess?.text = object.address
controller.phoNumber?.text = object.phoneNumber
controller.yearBirth?.text = String(object.age)
print(controller.fiName)
controller.detailItem = object
controller.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem()
controller.navigationItem.leftItemsSupplementBackButton = true
}
}
The result of the first print line is as I expect it to be, which is the name of the contact, but the program crashes on the second print, with an 'EXC_BAD_INSTRUCTION' / fatal error: unexpectedly found nil while unwrapping and optional value.
Why can I not set the controller.fiName?.text? Thank you in advance for any help.
Upvotes: 0
Views: 131
Reputation: 3753
You are setting the fiName label text too early, where the label hasn't been allocated yet. Instead pass through the object and then set the text in viewDidLoad of the next controller.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showDetail" {
if let indexPath = self.tableView.indexPathForSelectedRow {
let object = objects[indexPath.row]
let controller = (segue.destinationViewController as! UINavigationController).topViewController as! DetailViewController
//pass through object:
controller.object = object
print(object)
}
}
And then in the next viewController viewDidLoad set the text:
override viewDidLoad() {
//Now set the text value here:
fiName?.text = object.firstName
}
Upvotes: 2
Reputation: 816
Just object should be passed in prepareForSegue
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showDetail" {
if let indexPath = self.tableView.indexPathForSelectedRow {
let object = objects[indexPath.row]
let controller = (segue.destinationViewController as! UINavigationController).topViewController as! DetailViewController
controller.detailItem = object
controller.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem()
controller.navigationItem.leftItemsSupplementBackButton = true
}
}
}
And then outlets should be setup in viewDidLoad
class DetailViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
fiName?.text = detailItem.firstName
laName?.text = detailItem.lastName
miName?.text = detailItem.middleName
aess?.text = detailItem.address
phoNumber?.text = detailItem.phoneNumber
yearBirth?.text = String(detailItem.age)
}
}
Upvotes: 1
Reputation: 11435
I guess your filName
is an UILabel
or UITextField
right?
If you check your code in DetailViewController
you will notice this line:
@IBOutlet weak var filName: UITextField!
You see the !
at the end of the line?
This means, that the variable (aka outlet) filName
cannot be set at the initialization, but will be set at some point later.
Now, what you do is you init your class, and try to access that property that is not yet set at the initialization.
To get around this, create an object instance in DetailViewController
, and set that instance to the selected object, and then set the label properties in the viewDidLoad
function.
Something like this:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showDetail" {
if let indexPath = self.tableView.indexPathForSelectedRow {
let object = objects[indexPath.row]
let controller = (segue.destinationViewController as! UINavigationController).topViewController as! DetailViewController
controller.object = object
}
}
And then in the viewDidLoad
of DetailViewController
:
override viewDidLoad() {
fiName?.text = object.firstName
laName?.text = object.lastName
miName?.text = object.middleName
aess?.text = object.address
phoNumber?.text = object.phoneNumber
yearBirth?.text = String(object.age)
navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem()
navigationItem.leftItemsSupplementBackButton = true
}
Upvotes: 2