Reputation: 256
I have several UIViewController subclasses which need some instance data set before they can load properly.
For Example: - Note: This is a contrived example so apologies if I've missed some minor details - line 2 is the only part really necessary for the question.
class VehicleSpecificationsTableViewController: UITableViewController {
var vehicle: Vehicle! // <-- Implicitly unwrapped optional is my current solution
override func viewDidLoad() {
super.viewDidLoad()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return vehicle.specs.count // <-- Crashes here if the view ever loads/reloads when I'm not expecting it
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("vehicleSpecCell", forIndexPath: indexPath) as? VehicleSpecTableViewCell
cell.spec = vehicle.specs[indexPath.row]
return cell
}
}
The question is what type of variable should be used here as a best practice. I have been using optionals, but it's a pain having to unwrap them everywhere, so I'm converting to implicitly unwrapped optionals since I will be setting the variable before the view is loaded in general.
The problem is I'm worried about the controller getting reloaded at times when I'm not directly aware of it (after a memory warning, device rotation, awake from background, any other strange edge case). While I know this probably shouldn't happen, it still just seems really dangerous using an implicitly unwrapped optional if I'm not 100% sure that it's impossible for it to be nil at all times. So I'm thinking of placing a check somewhere to ensure that any implicitly unwrapped variables are actually set before load.
EDIT: A more likely scenario of it being nil is a second developer coming along in a few months and implementing something that uses my controller, and isn't aware that the instance variable needs to be set before it loads. While they should know better I suppose, it would result in a crash in production and that's what I'm trying to avoid. I want it to be impossible for it to crash without relying on convention (and hopefully not checking/unwrapping optionals in many/all functions)
So far I've found that putting the check in the viewDidLoad() is too late. I've tried putting it in viewWillAppear() but that doesn't work for things like UITableViewControllers because they attempt to load their data before the view attempts to appear.
Basic question is, has the Swift community decided on a best practice here? Does one use optionals and deal with unwrapping, implicitly unwrapped optionals and deal with nil checks in strategic places, non-optionals and add init() to each controller? Or is there a better solution I just haven't come across yet?
Any thoughts/suggestions would be greatly appreciated.
Upvotes: 0
Views: 304
Reputation: 23701
Your use of an implicitly unwrapped optional is fine, and just because you are using implicitly unwrapped optionals there is nothing to stop you from checking to see if the optional is nil before you use it.
Set a guard statement at the top of your functions to exit early if the variable is nil.
Upvotes: 0