BMI Calculator (3)
지난 글에서 코드로 label, frame 등 코드로 수작업을 해보았다.
확실히 수작업을 해보니 너무나도 불편했다. storyboard가 그리울줄이야..
그래서 여기서는 코드로 UserInterface를 작성하지 않고, 디자인 된 storyboard를 다른 view컨트롤러로 연결 하여 사용하는 것을 해보려한다.
우선 기존의 secondViewController는 이제 사용하지 않을것이다. (지워도 그만 아니어도 그만.)
난 그대로 냅둘 생각이다.
새로운 class file 생성
여태 우리는 file을 새로 만들때 Swift File을 선택하였다.
하지만 이번에는 Cocoa Touch Class를 선택하여 만든다.
습관이 무섭다고. 막 엔터치지말고 확인하면서 만들자.
CocoaTouch class ?
Apple이 만든 UIkit을 포함한 Framework이다.
아래 밑줄 친 곳에 우리가 naming을 해주면 된다.
이렇게 자동으로 만들어준다.
1
2
3
4
5
6
7
8
9
import UIKit
class ResultViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
Contoller와 StoryBoard 연결하기
만들어진 controller와 디자인된 storyboard를 연결하려면
2가지 방법이 있다. (단지 클릭의 차이)
- 먼저 storyboard로가서 디자인된 storyboard를 클릭
빨갛게 박스한 부분을 클릭
다음과 같이 Inspector Tab에서 네모로 표시한부분을 클릭
그리고 만들어진 컨트롤러 면을 적어준다. 그러면 링크 끝
- 왼쪽의 목록에서 viewController 선택
이후 inspector tap에서 똑같이 하면 된다.
그리고 Asistant view를 눌러보면 연결되어있는걸 볼 수 있다.
IBAction IBOutlet 연결해주기
설명은 생략하겠다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import UIKit
class ResultViewController: UIViewController {
@IBOutlet weak var bmiLabel: UILabel!
@IBOutlet weak var adviceLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func recalculatePressed(_ sender: UIButton) {
}
}
혹시라도 이름을 변경하고 싶다면?
이름을 명명한 부분을 우클릭하고 rename을 클릭해준다.
그러면 새로운 창으로 전환되는데 여기서 이름을 바꿔주면된다.
일반적으로 file의 이름이 그 기능의 전반적인걸 표시하게 하는 경우도 있으니 이름을 변경해보자
viewController → CalculateViewController로 변경.
변경이 잘 되었다.
Segue를 통한 viewController 초기화
전에 secondViewController를 viewController에서 사용할때 var secondVC = secondViewController()
이런식으로 초기화를 해서 사용하였다.
하지만 그렇게 하지않아도 된다.
다음과 같이 해주면된다
먼저 아까처럼 컨트롤러를 선택해준다. 위에서 1 이나 2의 방식으로.
그리고 IBOutlet, IBAction을 만들듯이 Control을 누른 상태로 드래그 해주자.
그리고 present modally를 선택해 주었다. (개취)
아래처럼 저렇게 해도 상관없다.
그 결과
세그웨이가 생성되었다.
insector tap을 통해 어떻게 애니메이션을 할지 설정 할 수 있다.
세그웨이에도 네이밍을 해주자.
identifier에 이름을 정해주면된다.
Segue를 사용하여 연결하기
우리는 CalulatorViewController에서 ResultViewController로 넘어가기에
perfromSegue메서드를 사용할 것이다.
1
self.performSegue(withIdentifier: "goToResult", sender: self)
- withIdentifier : 세그웨이의 이름
- sender : 일종의 전달자
세그를 사용하여 연결했으니 한번 작동 테스트를 해보자.
전환이 잘된다.
하지만 아직 계산값은 넘어가지 않는다.
BMI 값 전달하기
ResultViewController에서 전달값을 받을 변수 생성해주기
아래와 같이 생성했다. String으로 한건 값을 소수점표현하기 위해서이다.
var bmiValue : String?
그리고 다시 Calculate로 돌아와서
prepare 메서드를 생성해준다.
- 세그를 실행하기전 재정의 해야하는 override method이다.
보통 해당내용이 우리가 새로운 뷰컨트롤러를 만들게 되면 viewdidload 밑에 주석으로 처리되어있는 그 내용이다.
segue.identifier 가 goToResult일때 세그가 작동하게 하였다. 왜냐 우리가 viewContoller를 여러개 만들 수 있으니까.
그리고 destination을 설정해주어야 하는데.
destination은 기본적으로 UIViewController 형식이다 말그대로 도착지를 이야기 하는것이다.
그리고 그 도착지의 viewcontroller에 있는 bmiValue를 연결해준다.
그런데 에러가 난다?
UIViewController는 bmiValue가 없다고한다.
위의 적어놓은대로 UIViewController이지 우리가 원한 ResultViewController가 아니었던것이다.
그 상위 개념을 담아버렸다….
이럴땐 다운 캐스팅을 해주어 정확하게 지정해주자.
as를 사용한다.
as!를 사용하면서 강제로 다운캐스팅을 진행한다.
1
2
3
4
5
6
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToResult" {
let destinationVC = segue.destination as! ResultViewController
destinationVC.bmiValue = "0.0"
}
}
그렇다면 이제 calculated에있는 값을 result로 넘겨보자
난 이렇게 하였다.
일단 bmi를 새로 변수를 만들어 주었다.
weight, height를 서로 반대로 적어두고 계속 0.0 나와서 뭔가 싶었는데 저걸 잘못적어서 얼타버렸다…
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//CalculateViewController
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let bmi = weightSlider.value / pow(heightSlider.value,2)
print(bmi)
if segue.identifier == "goToResult" {
let destinationVC = segue.destination as! ResultViewController
destinationVC.bmiValue = String(format: "%.1f", bmi)
}
}
//ResultViewController
override func viewDidLoad() {
super.viewDidLoad()
bmiLabel.text = bmiValue
}
넘어온 값을 받아 보여주는 코드를 작성하였다.
강의에선 어떻게 했을까?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//CalculateViewController
var bmiValue = "0.0"
@IBAction func calculatePressed(_ sender: UIButton) {
let height = heightSlider.value
let weight = weightSlider.value
let bmi = weight / (height * height)
bmiValue = String(format: "%.1f", bmi)
self.performSegue(withIdentifier: "goToResult", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToResult" {
let destinationVC = segue.destination as! ResultViewController
destinationVC.bmiValue = bmiValue
}
}
//ResultViewController
override func viewDidLoad() {
super.viewDidLoad()
bmiLabel.text = bmiValue
}
이렇게 하였다.
실행화면
Segue를 다시 전환시키기
dismiss 메서드를 통해 다시 이전 view로 돌아갈 수 있다.
위의 실행화면은 수동으로 내렸지만, 이제는 버튼으로 가능해졌다.
1
2
3
@IBAction func recalculatePressed(_ sender: UIButton) {
self.dismiss(animated: true, completion: nil)
}
실행화면
UI를 3D로 볼 수도있다.
3D구현화면은 생략하겠다. 드래그로도 돌려 볼수있으니 나중에 시간 되면 해보는걸 추천한다.