[내일배움캠프 31일차] Ch.3 앱 개발 숙련 시작 + 알고리즘

NH·2025년 4월 14일

내일배움캠프

목록 보기
31/62
post-thumbnail

📱 Ch.3 앱 개발 숙련 시작!

새로운 주를 맞이 하면서 저번주에 진행했던 앱 개발 입문 주차에 이어 이번주는 앱 개발 숙련 주차의 시작이다!
앱 개발 숙련주차는 화면전환 데이터 관리, 네트워크 통신, 메모리 관리 를 배운다.

주차가 바뀌면서 새로운 팀으로 편성되었고, 이전 팀원들과 아쉬운 작별인사를 한 후, 새로운 팀원들과 만나는 시간을 가졌다.

새로운 조의 이름은 1찍 끝내시조 이다 데헷

오늘 TIL은 이번 주차에 들어온 새로운 강의를 들은 내용을 정리했고, 또 알고리즘 풀이를 한 것도 정리했다!

👨‍💻 강의 정리: ViewController 생명 주기

상태설명
init(coder:)- 초기화
loadView()- view를 메모리에 올릴때 호출됨.
- override 하지 않음.
- 커스텀 뷰를 수동으로 만들고 싶을 때 사용
viewDidLoad()- view가 메모리에 올라간 직후에 호출됨.
- 한번만 호출되며, 초기설정(view 구성, 데이터 로딩 등)에 주로 사용됨.
viewWillAppear(_:)- view 가 화면에 보이기 직전에 호출됨.
- 뷰가 나타날 때마다 호출되며, UI 업데이트나 애니메이션 준비 등에 사용함.
viewisAppearing(_:)- 뷰가 현재 화면에서 나타나는 중인지 아닌지 알려줌
viewDidAppear(_:)- view 가 실제로 화면에 나타난 후 호출.
- 사용자에게 보여지고 난 후 실행할 작업 (예: 애니메이션 시작, API 호출 등)
viewWillDisappear(_:)- view 가 사라지기 직전에 호출
- 저장되지 않는 데이터를 저장하거나, 타이머/애니메이션을 정지하는 데 사용.
viewDidDisapear(_:)- view 가 화면에서 완전히 사라진 후 호출
deinit- 소멸자
- 뷰 컨트롤러가 메모리에서 해제될 때 호출됨.
- 리소스 정리, 옵저버 제거 등을 할 수 있음.

실습

  • 생명주기에 대해 알아보기 위해 각 생명주기 메소드를 오버라이딩 하여 print()문을 추가하였다.
  • AdamViewController를 하나 더 추가해 화면 이동간 생명주기 동작을 확인 해보았다.
  • 화면이동을 위해 버튼을 추가했다.
    • 버튼을 누르면 AdamViewController로 이동하도록 하였다.

코드

// ViewController.swift

import UIKit
import SnapKit

class ViewController: UIViewController {
    
    private lazy var button: UIButton = {
        let button = UIButton()
        
        button.setTitle("다음 페이지로 이동", for: .normal)
        button.backgroundColor = .red
        button.setTitleColor(.white, for: .normal)
        button.addTarget(self, action: #selector(buttonTapped), for: .touchDown)
        
        return button
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        configureUI()
        
        print("viewDidLoad")
    }
    
    override func viewWillAppear(_ animated: Bool) {
        print("viewWillAppear")
        
        self.view.backgroundColor = UIColor(
            red: .random(in: 0...1),
            green: .random(in: 0...1),
            blue: .random(in: 0...1),
            alpha: 1.0
        )
            
        self.button.backgroundColor = UIColor(
            red: .random(in: 0...1),
            green: .random(in: 0...1),
            blue: .random(in: 0...1),
            alpha: 1.0
        )
    }
    override func viewIsAppearing(_ animated: Bool) {
        print("viewIsAppearing")
    }
    
    override func viewDidAppear(_ animated: Bool) {
        print("viewDidAppear")
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        print("viewWillDisappear")
    }
    
    override func viewDidDisappear(_ animated: Bool) {
        print("viewDidDisappear")
    }

    private func configureUI() {
        [button].forEach { view.addSubview($0) }
        
        view.backgroundColor = .white
        
        button.snp.makeConstraints {
            $0.center.equalToSuperview()
            $0.width.equalTo(300)
            $0.height.equalTo(120)
        }
    }
    
    @objc
    private func buttonTapped() {
        self.navigationController?.pushViewController(AdamViewController(), animated: true)
    }
}
// AdamViewController.swift

import UIKit

class AdamViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .orange
        print("AdamViewController viewDidLoad")
    }
}

앱 실행

  • 아래와 같이 생명주기가 동작하는 것을 확인했다.

화면 이동

  • 화면 이동을 하면, viewWillDisappearviewDidDisappear 나타나는 것을 볼 수 있다.

다시 화면 이동

  • viewWillAppear, viewIsAppearing, viewDidAppear 나타나는 것을 볼수있다.
  • viewDidLoad는 나타나지 않는다. 왜냐면 최초 한번만 나타나기 때문이다.

강의에서 배운 점

코드베이스에서 네비게이션 컨트롤러 사용법

  • window.rootViewController 에서 UINavigationController(rootViewController:)을 사용하면 네이게이션 컨트롤러를 사용 가능하다.
import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?


    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        
        guard let winsdowScene = scene as? UIWindowScene else { return }
        
        let window = UIWindow(windowScene: winsdowScene)
        
        window.rootViewController = UINavigationController(rootViewController: ViewController())
        window.makeKeyAndVisible()
        
        self.window = window
    }
}

🏆 알고리즘 풀기!

👏 369 게임

프로그래머스 링크 이동

🔹 문제 설명

머쓱이는 친구들과 369게임을 하고 있습니다. 369게임은 1부터 숫자를 하나씩 대며 3, 6, 9가 들어가는 숫자는 숫자 대신 3, 6, 9의 개수만큼 박수를 치는 게임입니다. 머쓱이가 말해야하는 숫자 order가 매개변수로 주어질 때, 머쓱이가 쳐야할 박수 횟수를 return 하도록 solution 함수를 완성해보세요.

🔹 제한 사항

1 ≤ order ≤ 1,000,000


🔹 첫 시도

코드

import Foundation

func solution(_ order:Int) -> Int {
    return Array(order).filter { $0 == 3 || $0 == 6 || $0 == 9 }.count
}

결과: 실패

오류 발생..

/Solution/Sources/Solution/Solution.swift:4:66: error: the compiler is unable to type-check this expression in reasonable time; 
try breaking up the expression into distinct sub-expressions
    return Array(order).filter { $0 == 3 || $0 == 6 || $0 == 9 }.count

실패한 코드 분석

  • Array(Int)는 "Int를 배열로 변환하겠다" 라는 의미가 아님
  • "Int 값을 요소로 가진 배열을 만들겠다" 라는 의미
    • 예) Array(5) -> [0, 1, 2, 3, 4, 5]
  • 테스트 케이스에 29423 가 있었으니.. 에러가 날 만도 하다..
  • 따라서 String() 를 사용하기로 했다.

🔹 두번째 시도

코드

  • String()을 사용하여, filter3,6,9가 포함된 요소만 가져와 개수를 리턴했다!
import Foundation

func solution(_ order:Int) -> Int {
    return String(order).filter { $0 == "3" || $0 == "6" || $0 == "9" }.count
}

결과: 성공


🔹 제출

코드

  • filter 조건이 너무 길어서 바꿔보았다.
import Foundation

func solution(_ order:Int) -> Int {
    return String(order).filter { "369".contains($0) }.count
}


🔹 제한 사항 추가

코드

import Foundation

func solution(_ order:Int) -> Int {
    guard order >= 1 || order <= 1000000 else { 
        print("Error")
        return 0
    }
    
    return String(order).filter { "369".contains($0) }.count
}
profile
iOS 개발 블로그

0개의 댓글