iOS/ios 아무거나 만들어보기

1. 가위바위보 만들어보기 (view 클릭 이벤트 넣기)

728x90

처음 iOS를 배울 때 Storyboard를 사용하여 View를 구성 하였는데 너무 불편했다.

새로운 화면을 만들 때 마다 마우스로 클릭, 클릭, 드래그 이런 작업이 너무 지쳤고 UI가 변경되거나 수정되었을 때도 View를 만드는게 너무 귀찮아서 코드로 UI를 짜보기로 했다.

 

기본적인 개념을 알기위해 여러가지를 만들건데 클릭 이벤트를 알아보기 위해 가위바위보 앱을 만들어보자.

 

기능: 

- 화면 터치 시 랜덤으로 가위바위보 중 한개를 보여줌.

 

구현:

 

우선 가위바위보에 사용 될 이미지와 label를 코드로 생성해주자.

// MARK: Properties
    
/// 가위바위보가 표현될 이미지
/// 기본 값은 Empty로 설정
private var handImageView: UIImageView = {
    let iv = UIImageView(image: UIImage(named: "Empty"))

    iv.translatesAutoresizingMaskIntoConstraints = false
    iv.heightAnchor.constraint(equalToConstant: 200).isActive = true
    iv.widthAnchor.constraint(equalToConstant: 200).isActive = true

    return iv
}()

/// 가위바위보 중 하나의 텍스트
/// 기본 값은 "빈 값"으로 설정
private var handLabel: UILabel = {
    let label = UILabel()
    label.font = UIFont.systemFont(ofSize: 34, weight: .semibold)
    label.text = "빈 값"
    return label
}()

 

그런 다음 StackView를 생성해 이미지와 텍스트를 넣어주자.

 // MARK: LifeCycle
override func viewDidLoad() {
    super.viewDidLoad()

    let stackView = UIStackView(arrangedSubviews: [handImageView, handLabel])
    stackView.axis = .vertical       // 세로 방향으로 뷰를 쌓음
    stackView.alignment = .center   // 가운데 정렬
    stackView.spacing = 16           // 뷰 간의 간격 설정

    view.addSubview(stackView)
    stackView.translatesAutoresizingMaskIntoConstraints = false
    stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 80).isActive = true
    stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
}

 

translatesAutoresizingMaskIntoConstraints는 Constraint를 사용하기 위해선 false로 지정해줘야한다.

코드 방식으로 생성된 뷰의 경우 기본값은 true 이고 Interface Builder의 기본값은 false 설정되는데, 코드로 생성된 뷰의 제약조건을 주기 위해선 false로 바꿔주어야 한다.

 

 

코드를 추가하게 되면 이런 뷰가 나오는데, 클릭 이벤트를 넣어보자.

iOS에서 View -> Controller 사이의 의사소통을 위해 여러 제스쳐를 지원하는데 그 중 UITapGestureRecognizer라는 제스쳐를 인식하게 하고, 동작하는 함수를 넣어주자.

 

Gesture는 viewDidLoad 라이프 사이클에 넣어주자.

	 // background tap
	let bgtap = UITapGestureRecognizer(target: self, action: #selector(handleBackgroundViewTapped))
	self.view.addGestureRecognizer(bgtap)
}


// MARK: Selector
/// Background 터치 시 동작하는 함수
@objc func handleBackgroundViewTapped() {
    print("DEBUG: 백그라운드를 클릭 했습니다.")
}

 

클릭이 잘 되는지 확인하고, 앱의 핵심 기능인 image와 text를 랜덤하게 변경하는 기능을 넣어보자.

가위, 바위, 보 셋 중 하나의 항목만 나오기 때문에 enum을 사용하여 보다 명확하게 작성해보자.

/// 가위,바위,보를 가지고 있는  enum 이다
/// Array가 가지고 있는 randomElement()를 사용하기 위해 CaseIterable 프로토콜을 상속받았다.
/// Rock, Scissors, Paper은 이미지 이름에 사용된다.
enum Hand: String, CaseIterable{
    case Rock
    case Scissors
    case Paper

    var description: String {
        switch self {
        case .Rock:
            return "바위"
        case .Scissors:
            return "가위"
        case .Paper:
            return "보"
        }
    }
}

/// Background 터치 시 동작하는 함수
@objc func handleBackgroundViewTapped() {
    let randomHand = Hand.allCases.randomElement()!
    handImageView.image = UIImage(named: randomHand.rawValue)
    handLabel.text = randomHand.description
}

 

클릭 할 때 마다 잘 동작하는지 확인해보자.

가위,바위,보

 

 

 

 

 

전체 코드

//
//  ViewController.swift
//  RockScissorsPaper
//
//  Created by Taehoon Kim on 2022/02/08.
//

import UIKit

class ViewController: UIViewController {
    
    // MARK: Properties
    
    /// 가위바위보가 표현될 이미지
    /// 기본 값은 Empty로 설정
    private var handImageView: UIImageView = {
        let iv = UIImageView(image: UIImage(named: "Empty"))
        
        iv.translatesAutoresizingMaskIntoConstraints = false
        iv.heightAnchor.constraint(equalToConstant: 200).isActive = true
        iv.widthAnchor.constraint(equalToConstant: 200).isActive = true
        
        return iv
    }()
    
    /// 가위바위보 중 하나의 텍스트
    /// 기본 값은 "빈 값"으로 설정
    private var handLabel: UILabel = {
        let label = UILabel()
        label.font = UIFont.systemFont(ofSize: 34, weight: .semibold)
        label.text = "빈 값"
        return label
    }()

    
    // MARK: LifeCycle
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let stackView = UIStackView(arrangedSubviews: [handImageView, handLabel])
        stackView.axis = .vertical       // 세로 방향으로 뷰를 쌓음
        stackView.alignment = .center   // 가운데 정렬
        stackView.spacing = 16           // 뷰 간의 간격 설정
        
        view.addSubview(stackView)
        stackView.translatesAutoresizingMaskIntoConstraints = false
        stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 80).isActive = true
        stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        
        // background tap
        let bgtap = UITapGestureRecognizer(target: self, action: #selector(handleBackgroundViewTapped))
        self.view.addGestureRecognizer(bgtap)
    }
    
    // MARK: Selector
    
    /// 가위,바위,보를 가지고 있는  enum 이다
    /// Array가 가지고 있는 randomElement()를 사용하기 위해 CaseIterable 프로토콜을 상속받았다.
    /// Rock, Scissors, Paper은 이미지 이름에 사용된다.
    enum Hand: String, CaseIterable{
        case Rock
        case Scissors
        case Paper
        
        var description: String {
            switch self {
            case .Rock:
                return "바위"
            case .Scissors:
                return "가위"
            case .Paper:
                return "보"
            }
        }
    }

    /// Background 터치 시 동작하는 함수
    @objc func handleBackgroundViewTapped() {
        let randomHand = Hand.allCases.randomElement()!
        handImageView.image = UIImage(named: randomHand.rawValue)
        handLabel.text = randomHand.description
    }

}

github: https://github.com/HOONITANG/RockScissorsPaper

반응형