Update note: This tutorial has been updated for Xcode 9, iOS 11, and Swift 4 by Nicholas Sakaimbo. The original tutorial was written by Matthijs Hollemans.
If you want to learn about storyboards, you’ve come to the right place!
In the first part of this series, you covered the basics of using Interface Builder to create and connect various view controllers, along with how to make custom table view cells directly from the storyboard editor.
In this second and final part of this storyboards tutorial series, we’ll cover segues, static table view cells, the Add Player scene, and game picker scene!
We’ll start where we left off last tutorial, so open your project from last time, or download the example code from the previous tutorial here.
OK, now you’ll dive into some of the other cool features in storyboards!
It’s time to add more view controllers to the storyboard. You’re going to create a scene to add new players to the app.
(bar button 만들기 (navigation button) 방법)
Open Main.storyboard and drag a Bar Button Item into the right slot of the navigation bar on the Players scene. In the Attributes inspector change System Item to Add, and set its Style to Bordered.
When the user taps this button, you want the app to pop up a new modal scene for entering details of a new player.
(bar button(navigation button) 과 다른 view controller를 segues로 연결하는 방법)
Drag a new Table View Controller into the canvas to the right of the Players scene. Remember you can double-click the canvas to zoom out so you have more room to work. With the new Table View Controller selected, choose EditorEmbed inNavigation Controller.
Here’s the trick: Select the + button you just added on the Players scene and ctrl-drag to the new Navigation Controller. Release the mouse button and select Present Modally from the popup menu:
This places a new arrow between the Players scene and the Navigation Controller:
This type of connection is known as a segue (pronounce: seg-way) and represents a transition from one scene to another. The storyboard connections you’ve seen so far were relationships and they described one view controller containing another. A segue, on the other hand, changes what’s on the scene. Segues are triggered by taps on buttons, table view cells, gestures, and so on.
The cool thing about using segues is you don’t have to write any code to present the new scene, or hook up your buttons to IBAction methods. What you just did, dragging from the Bar Button Item to the next scene, is enough to create the transition. (Note: If your control already has an IBAction connection, the segue overrides it.)
Build and run the app and tap the + button. A new table view will slide up from the bottom.
This is called a modal segue. The new scene completely obscures the previous one. The user cannot interact with the underlying scene until they close the modal scene first. Later you’ll see “show” segues that push a new scene onto a Navigation Controller’s navigation stack.
The new scene isn’t very useful yet – you can’t even close it to go back to the main scene. That’s because segues only go one way – so while it can go from the Players scene to this new one, it can’t go back.
(segue는 일방향으로 진행된다. 즉 segue를 통해 열려진 view controller는 다시 돌아 갈수 없다. 그러므로 이를 수행할수 있게 추가 작업이 필요한데 그 작업에 대한 방법 설명)
Storyboards provide the ability to ‘go back’ with something called an unwind segue, which you’ll implement next. There’s three main steps:
Create an object for the user to select, usually a button.
Create an unwind method in the controller you want to return to.
Hook up the method and the object in the storyboard.
First, open Main.storyboard and select the new Table View Controller scene. Change the title of the scene to Add Player (by double-clicking in the navigation bar). Next, add two Bar Button Items, one to each side of the navigation bar. In the Attributes inspector, set the System Item property of the left button to Cancel, and the right button to Done.
Next, add a new file to the project using the Cocoa Touch Class template – name it PlayerDetailsViewController and make it a subclass of UITableViewController. Next, open Main.storyboard and select the Add Player scene. In the Identity inspector set its Class to PlayerDetailsViewController. I always forget this very important step, so to make sure you don’t; I’ll keep pointing it out.
Now you can finally create the unwind segue. Open PlayersViewController.swift, add the following extension above your UITableViewDataSource extension:
cancelToPlayersViewController(_:) is simply a marker for the unwind segue. Later you’ll add code to savePlayerDetail(_:) to allow it to live up to it’s name!
Finally, open Main.storyboard and hook up the Cancel and Done buttons to their respective action methods. Ctrl-drag from the bar button to the exit object above the view controller then pick the correct action name from the popup menu:
Note the name you gave the cancel method. When you create an unwind segue, the list will show all unwind methods (i.e. ones with the signature @IBAction func methodname(_ segue:)) in the entire app, so create a name you can recognize.
Build and run the app, tap the + button, and test the Cancel and Done buttons. A lot of functionality for very little code!
(static cell 만드는 방법)
Storyboards Static Cells
When you’re finished with this section, the Add Player scene will look like this:
That’s a grouped table view, but you don’t have to create a data source for this table. You can design it directly in the storyboard — no need to write tableView(_:cellForRowAt:) for this one! Static cells is the feature that makes this possible.
(static cell 스타일링 방법)
Open Main.storyboard and select the table view in the Add Player scene. In the Attributes inspectorchange Content to Static Cells. Change Style from Plain to Grouped and give the table view 2 sections.
Note: When you change the value of the Sections attribute, the editor will clone the existing section. (You can also select a specific section in the Document Outline on the left and duplicate it.)
The finished scene will have only one row in each section, so select two cells in each of the sections and delete them using the Document Outline.
Next, select the top table view section (from the Document Outline) and set the header value to Player Name.
Drag a new Text Field into the cell for this section. Stretch out its width and remove its border so you can’t see where the text field begins or ends. Set the Font to System 17.0 and uncheck Adjust to Fit.
(간단하게 canvas의 요소를 controller코드상에서 outlet으로 연결하는 방법)
You’re going to make an outlet for this text field on the PlayerDetailsViewController using the Assistant Editor feature of Xcode. While still in the storyboard, open the Assistant Editor with the button from the toolbar (the one at the top right with two intertwining rings). It should automatically open on PlayerDetailsViewController.swift (if it doesn’t, use the jumpbar in the right hand split window to select PlayerDetailsViewController.swift).
Select the new text field and ctrl-drag(오르쪽클릭은 outlet,왼쪽클릭은 action) to the top of PlayersDetailViewController, just below the class definition. When the popup appears, name the new outlet nameTextField, and click Connect. Xcode will add the property to the PlayersDetailViewController class and connect it in the storyboard:
Creating outlets for views on your table cells is exactly the kind of thing I said you shouldn’t try with prototype cells, but for static cells it’s OK. There will be only one instance of each static cell so it’s perfectly acceptable to connect their subviews to outlets on the view controller.
Select the second section of the table view in the Document Outline and delete the placeholder “Section-2” text in the Header field in the Attributes Inspector. Set the Style of the static cell in the second section to Right Detail. This gives you a standard cell style to work with. Change the label on the left to read Game by double clicking it and give the cell a Disclosure Indicator accessory.
Just as you did for nameTextField, make an outlet for the label that says Detail and name it detailLabel. The labels on this cell are just regular UILabel objects. You might need to click a few times on the text “Detail” to select the label (and not the whole cell) before ctrl-clicking and dragging to PlayerDetailsViewController.swift. Once done, it will look similar to the following:
The final design of the Add Player scene looks like this:
Note: The scenes you’ve designed so far in this storyboard all have the width and height of the 4.7-inch screen of the iPhone 7, which is 667 points tall. Obviously, your app should work properly with different screen sizes, and you can preview these sizes within your Storyboard.
Open the Assistant Editor from the toolbar, and use the jump bar to select Preview. At the bottom left of the assistant editor, click the + symbol to add new screen sizes to preview. To remove a screen size, select it and hit the Delete key.
For the Ratings app, you don’t have to do anything fancy. It only uses table view controllers and they automatically resize to fit the screen space. When you do need to support different layouts for different sized devices, you’ll use Auto Layout and Size Classes.
Build and run the app. You’ll notice the Add Player scene is still blank!
(static cell의 경우 기존 table view controller가 가지고 있는 요소를 제거해야 제대로 작동한다. 그런 정리 작업 방법)
When you use static cells, your table view controller doesn’t need a data source. Since you used an Xcode template to create the PlayerDetailsViewController class, it still has some placeholder code for the data source and this prevents the static cells from working properly. Time to fix it!
Open PlayerDetailsViewController.swift and delete everything from the following line down (except for the class closing bracket):
Build and run the app. Now the new scene displays the static cells, and all without writing a line of code.
One more thing about static cells: they only work in UITableViewController. Even though Interface Builder will let you add them to a table view inside a regular UIViewController, this won’t work during runtime. The reason is UITableViewController provides some extra magic to take care of the data source for the static cells. Xcode prevents you from compiling such a project with the error message: “Illegal Configuration: Static table views are only valid when embedded in UITableViewController instances”. Prototype cells, on the other hand, work just fine in table view’s placed inside regular view controllers.
Note: If you’re building a scene with a lot of static cells — more than can fit in the visible frame — you can scroll through them in Interface Builder with the scroll gesture on the mouse or trackpad (2 finger swipe).
You can’t always avoid writing code altogether though, even for a table view of static cells. When you dragged the text field into the first cell, you probably noticed it didn’t fit completely. There’s a small margin of space around the text field. The user can’t see where the text field begins or ends, so if they tap in the margin and the keyboard doesn’t appear, they’ll be confused.
(특정 요소를 first responder 로 만드는 방법 )
To avoid this, let a tap anywhere inside the row bring up the keyboard. OpenPlayerDetailsViewController.swift and add the following extension to the end of the file:
If the user taps the first cell, the app should activate the text field. There’s only one cell in the section so you only need to test for the section index. Making the text field the first responder will automatically bring up the keyboard.
Note: when adding a delegate method, or overriding a view controller method, just start typing the method name (without preceding it with “func”), and you’ll be able to select the correct method from the available list.
You should also set the Selection for the cell to None in the storyboard Attributes Inspector, otherwise the row appears highlighted when the user taps in the margin around the text field.