간단한 카운터 앱 만들기
레이아웃 요구사항
- UILabel이 가운데 위치
- "UILabel"을 기준으로 상단 : 감소
, 아래 : 증가 버튼을 위치
- "UILabel"과 "UIButton"사이의 간격은 "16px"
- "AutoLayout" 사용
로직 요구사항
"count"의 시작 = "0"
감소버튼 : "-1"씩 감소시켜 "UILabel"에 표시
증가버튼 : "+1"씩 증가시켜 "UILabel"에 표시
UI View 구현
먼저 스토리보드 상에서 UI를 그려주어야겠죠?
그러기 위해서는 레이블을 만들어 주시고 0을 입력해줍시다.
그리고 제약조건을 걸어서 요구사항 대로 한 가운데에 배치해 줍시다.
Horizontally in Container, Vertically in Container 각각 0으로 체크 해주시면 됩니다.
이후 버튼들은 0 근처로 드래그로 가져다 주시고 요구사항 대로 16px정도 띄어 줍시다.
이후, 사진에서 양쪽이 빨간 색 선이 보이시죠?
이건 양쪽 제약 조건을 안걸었기 때문에 그러는 거죠? ㅎㅎ
마찬가지로 제약조건을 걸어줍시다.
이렇게 하시면 다음과 같은 화면이 나오게 될 겁니다.
그리고 이제 코드를 짜봅시다.
먼저 각각의 버튼이 눌리면 카운팅 될 수 있도록 하기 위해서
레이블을 먼저 연결 해보도록 합시다.
스토리보드와 코드를 연결하려면 컨트롤+드래그로 연결 해야겠죠?
레이블의 경우 IB를 Outlet으로 주어 참조를 할 수 있도록 해줍시다.
여기서 잠깐! IBOutlet과 IBAction에 대해 알고 있으신가요?
IBOutlet / IBAction의 차이점은
둘 다 Interface Builder를 통해서 UI 요소를 코드와 연결하는 역할을 하는데,
각각의 역할과 사용되는 시점에서 차이가 있다는 점을 알아야 해요
IBOutlet의 경우
Interface Builder에서 디자인한 UI 요소(ex. 버튼, 라벨, 텍스트 필드 등)를
코드에 연결하는 데 사용 하고 UI 요소의 속성을 변경하거나,
해당 UI 요소에 프로그래밍적으로 접근하고 제어할 수 있도록 해요
주로 UI 요소의 상태를 프로그래밍적으로 변경하거나,
UI 요소에 데이터를 설정하는 등의 작업에 사용해요
IBAction의 경우
UI 요소(ex. 버튼)의 특정 이벤트(ex. 탭, 드래그 등)에 대한 응답으로 호출되는
메서드를 정의하는 데 사용되는 점
사용자가 UI 요소와 상호작용할 때 발생하는 이벤트를 처리하고,
해당 이벤트에 대한 작업을 수행할 수 있도록 하는데
주로 버튼이나 다른 상호작용 가능한 UI 요소를
사용자의 행동에 반응하도록 구현할 때 사용된다고 합니다.
쉽게 말해서 IBOutlet은 단순히 UI적 요소를 조정하는데 그 목적을 두고 있고,
IBAction의 경우 말 그대로 사용자의 특정한 행동에 의한 부분들을 조정하는데 그 목적을 둔다는 것이죠.
때문에 위에서 주어진 Lable의 경우에는 사용자에게 입력을 받으면 그 숫자가 변해야 하기 때문에
IBOutlet으로 디자인적 조정을 받아야 하며, button 버튼요소는 당연히 사용자에게 입력을 받아야 하기 때문에
특정 이벤트를 실행을 해야하고 메서드를 정의해야하기 때문에 IBAction을 사용 해야합니다.
그렇다면 어떻게 UI적 요소의 디자인을 입히고, 어떻게 메서드를 정의를 하느냐?
여기부터는 심플합니다.
이건 간단하게 카운트를 하기 위한 어플이잖아요?
그러기 위해서 생각해야할 함수 그리고 로직은 무엇인가?
반복해서 올리고 내리고 해야하니 변수를 사용해야할 것이고,
숫자를 세야 하니까 정수인 Int를 생각해볼 수 있겠죠?
그리고 버튼을 클릭하면 + 혹은 - 될 수 있도록 해야하니 이것도 고안해야 하겠구요
첫번째로
0의 레이블을 연결해 줍시다.
그리고 카운트를 해주고, 정수로 입력을 받는데 0으로 초기화해라
그러면 이제 count라는 변수가 생성되었죠? 이제 입력을 받으면,
count가 증가하거나 감소될 수 있도록 설계를 해주어야 겠죠?
위와 같이 증가 되었을 때와 감소되었을 때의 액션의 구조를 선언 해주고,
이제 값을 주면 되겠죠?
어떻게?
우리가 위에서 만든 변수를 활용하면 되겠죠?
여기서 'self'를 쓰는건 명시적으로 CountUp과 CountDown의 객체를
가르키기 위해서 사용하는 것이고,
이대로 우선 실행해 봅시다.
어? 근데 오류가 났죠?
이 오류는 "IBOutlet"과 연결이 안됐다는 의미기도 한데,
문제는 대소문자 일까요?
스위프트는 대소문자를 가리기 때문에
아마도 Interface Builder에서 "CuntUpDown"라는 아울렛을 만들었지만,
실제 코드에서는 "cuntUpDown" 조합으로 정의가 되어 있을 합리적 의심이 들죠?!
그러면 바꿔봅시다.
추가적으로 이름을 변경하거나 다시 등록할 때 주의할 점은
오른쪽 "Referencing Outlets Outlets"를 잘 살펴야 하죠,
안그러면 또 오류 나서 화가 치밀어 오를 수 있다는 점..
그런데
저는 또 위와같이 오류가 났는데...
똑같은 오류의 이름으로 "IBOutlet"과 연결이 안됐다는 의미로 나더라구요.
생각해 볼 수 있는 원인과 해결 방법으로는
어디선가 연결이 제대로 이루어지지 않아서 그런 걸 꺼라고 생각해볼 수 있겠죠?
이게.. 스토리보드의 가장 큰 문제점입니다..
저는 해결하기 위해서 우선 스토리보드상의
ViewController와 코드상의 ViewController가 연결이 잘 되어 있는가를
보고 왔는데 아니나 다를까.. 혹시나 하는 마음에 다시 입력을 했는데
역시는 역시네요...
필자의 경우 클래스는 정의가 되어 있었는데 "Module"이 정상적으로 작동 하지 않아서
다시 클래스를 주었더니 작동 합니다.
이처럼 스토리보드 상에서는
여러가지 오류들이 자주 발생한다는 점 참고 하시길 바랍니다.
그런데
정의 된 대로라면 작동이 되어야 하는데,
버튼을 눌러도 무반응입니다.
이유는 왜 일까요?
현재상태를 저장하는 메소드가 없고,
"text"에 반영되지 않아서 그런거겠죠?
저는 카운터를 + 할때 1을 씩 증가하게 끔 메소드를 정의를 했는데
증가만 하고 저장을 하는 메소드를 정의해주지 않아서
업데이트 되는 숫자가 반영이 안되는 상황이 주어지고 있어요
때문에
"textLabelUpdate"라는 메소드를 정의 해주고 +를 누르면 그 상태를 저장하라
라는 메소드를 정의 해줍시다.
그리고
이를 반영 하기 위해서는 함수를 정의 해주어야 겠죠?!
함수를 정의 해줄 때에는
반드시
소문자로 시작 해 주어야 하는 점 알아두셔야 합니다.
함수를 정의를 어떻게 해주면 될까요?
문제를 잘 생각해야해요
버튼을 누르면 먼저 어떤게 변할까요 -> 숫자가 변하잖아요?
그렇다면 이 숫자는 현재 UILabel에 들어가 있고,
UILabel의 text 속성은 Int가 아닌 String 이기 때문에 문자열로 정의해 줍시다.
그리고, 여기서 파라미터는 "cuntUpDown"이 되겠죠?!
self 속성은 굳이 붙일 필요는 없지만 이후 많은 데이터를 다루면 꼬일 수도 있어서
붙여주는게 명확성 면에서는 웬만해서는 써주는게 좋다고 합니다.
그리고 함수를 정의 했다면
오버라이드에 생명을 불어넣어 주어야 하죠?!
이렇게 하면 아래와 같이 작동이 잘 됩니다~
import UIKit
class MyCountViewController: UIViewController {
@IBOutlet weak var cuntUpDown: UILabel!
var count: Int = 0 // 카운터를 해라, 정수로, 0부터
@IBAction func CountUp(_ sender: Any) { // 증가 되었을 때 ~
count += 1 // 1씩 증가하라
textLabelUpdate() // 현재상태 반영
}
@IBAction func CountDown(_ sender: Any) {// 감소 되었을 때 ~
count -= 1 // 1씩 감소하라
textLabelUpdate() // 현재상태 반영
}
// 업데이트 반영에 대한 메서드 정의
func textLabelUpdate () { // count값을 Label에 text에 반영 해주자~
cuntUpDown.text = String(count)
}
override func viewDidLoad() {
super.viewDidLoad()
textLabelUpdate()
// Do any additional setup after loading the view.
}
}
'IOS > Swift-TIL' 카테고리의 다른 글
[Swift-TIL] 컬렉션 - 여러 변수를 만드는법 (Set편) (0) | 2024.10.09 |
---|---|
[Swift-TIL] 컬렉션 - 여러 변수를 만드는법 (Array편) (0) | 2024.10.09 |
[Swift-TIL] 변수타입 - 데이터의 종류 (0) | 2024.10.09 |
[Swift-TIL] 변수 - 값 저장, 다루는 법 2편 (0) | 2024.10.09 |
[Swift-TIL] 변수 - 값 저장, 다루는 법 1편 (0) | 2024.10.08 |