In past posts of test-driven iOS, we have talked about instantiating view controllers with dependencies. What if we want to pass information from one view controller to the next one?
Let’s explore how we would test-drive a storyboarded iOS application that passes information from a master list view controller to a detail view controller.
We’ll write an application about fruit!
FROOOOOOOT
Our work will require two steps:
Step 1: Test
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import XCTest | |
import Hamcrest | |
import FutureKit | |
@testable import FruitApp | |
class ListOfFruitsViewControllerTest: XCTestCase { | |
… | |
func testShowsFruitDetailsWhenFruitRowIsTapped() { | |
let orange = FruitAppFruit(name: "Orange") | |
fruitService.stubbedFruits = [orange] | |
… | |
fruitListController.tableView(fruitListController.fruitTableView, didSelectRowAtIndexPath: NSIndexPath(forRow: 0, inSection: 0)) | |
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.001, false) | |
assertThat(navigationController.topViewController, presentAnd(instanceOf(FruitDetailViewController.self))) | |
let fruitDetailsController = navigationController.topViewController as! FruitDetailViewController | |
assertThat(fruitDetailsController.fruit, presentAnd(equalTo(orange))) | |
} | |
} |
Here we tap on one element in the master view controller and make sure that the next presented view controller is the detail view controller. We also check that the object the detail view controller will display—an orange!—has been set on the detail view controller.
If we’re not presenting the view controller manually, then we cannot call an initializer on it that sets this property for us. So how do we pass it in?
Step 2: prepareForSegue()
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
import FutureKit | |
class ListOfFruitsViewController: UITableViewController { | |
… | |
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { | |
if (segue.identifier == "goToFruitDetailsSegue") { | |
if let | |
fruitDetailController = segue.destinationViewController as? FruitDetailViewController, | |
selectedFruit = self.selectedFruit | |
{ | |
fruitDetailController.fruit = selectedFruit | |
} | |
} | |
} | |
} |
This handy method gives us access to the view controller that our segue will present right before we present it. This means that we can get ahold of our destination view controller and set our selected fruit.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
class FruitDetailViewController: UIViewController { | |
var fruit: FruitAppFruit? | |
… | |
} | |
The detail view controller itself has a field attribute on it that you saw us set in the last code snippet. we’ll have access to this throughout the view controller, so we can display all our orange information in there!