Reputation: 55
I'm new to Swift, and I find some strange crashes in my app.
The Fabric reports said crashes occurred in viewWillDisappear().
I have two ViewControllers.User tap button in A viewcontroller then they move to B viewcontroller to input something, they user go back, and A get information from B.
I use a delegate to complete this task.
B:
class LessonNameTagTableViewController: UITableViewController {
...
var delegate:PassingData?
override func viewWillDisappear(_ animated: Bool) {
lessonName = (tableView.cellForRow(at: IndexPath(row: 0, section: 0))?.viewWithTag(1) as! UITextField ).text!
delegate?.changeLessonNameTag(name: lessonName, tag: tagColor)
super.viewWillDisappear(animated)
}
...
}
A:
class LessonEditTableViewController: UITableViewController,PassingData {
var lesson :Lesson?
...
func changeLessonNameTag(name:String,tag:UIColor){
self.lesson!.lessonName = name
self.lesson!.lessonTagColor = tag
tableView.reloadData()
}
...
}
The crash happened randomly, I've tested it on my device, and nothing happened.But others said they could repeat this crashes.
I wonder whether I'm using delegate right or it's caused by other reasons.
Upvotes: 0
Views: 830
Reputation: 5694
If IndexPath{0,0}
isn't visible when viewWillDisappear
is called, then this line will set lessonName = nil
as there is no cell for that row. That will cause the following line to crash.
lessonName = tableView.cellForRow(at: IndexPath(row: 0, section: 0))?.viewWithTag(1) as! UITextField ).text!
As others have mentioned, there are too many forced unwrappings.
However, unless that cell was dynamically populate by the user, you should be able to get the same value from your UITableViewDataSource
- so it will work if the cell is visible or not.
Additionally, don't force unwrap lesson
in your delegate method - could be nil
.
func changeLessonNameTag(name:String,tag:UIColor){
self.lesson?.lessonName = name
self.lesson?.lessonTagColor = tag
tableView.reloadData()
}
Upvotes: 1
Reputation: 1380
My gut reaction is that one of the object's you're force unwrapping is in fact nil
.
Instead of force unwrapping it using the !
, you should safely unwrap it and fail gracefully if it is not present:
func changeLesson(name: String, tag: UIColor) { //Updated formatting and method declaration to fit with current Swift standards
guard let lesson = lesson else { //Don't need to reference self here
return
}
lesson.lessonName = name
lesson.lessonTagColor = tag
tableView.reloadData()
}
See @orxelm's answer for how to safely unwrap your text value in B
Always be very wary when using the !
operator. Even if you think you can guarantee that the object will not ever be nil.
Upvotes: 0
Reputation: 1144
You probably have a problem in you viewWillDisappear, there's many optionals there that can cause you trouble when you force-unwrap.
It's better to be crash safe:
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if let lessonName = (tableView.cellForRow(at: IndexPath(row: 0, section: 0))?.viewWithTag(1) as? UITextField)?.text {
delegate?.changeLessonNameTag(name: lessonName, tag: tagColor)
}
}
Upvotes: 1