info
plist에서 삭제import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
// 윈도우. 앱에 반드시 한 개는 필요한 가장 근본이 되는 뷰. 이 위에 뷰가 쌓이기 시작.
var window: UIWindow?
// 앱을 시작할 때 세팅해줄 코드들을 작성해주는 곳.
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
//guard let _ = (scene as? UIWindowScene) else { return }
// UIWindowScene 객체 생성.
guard let windowScene = scene as? UIWindowScene else { return }
let window = UIWindow(windowScene: windowScene)
// window 에게 루트 뷰컨트롤러 지정.
window.rootViewController = CalculatorViewController()
// 이 메서드를 반드시 작성해줘야만 윈도우가 활성화가 됨
window.makeKeyAndVisible()
self.window = window
}
calculatorView.buttonStack.arrangedSubviews
.compactMap { $0 as? UIStackView } // 중첩된 UIStackView만 필터링
.flatMap { $0.arrangedSubviews } // 중첩된 StackView의 하위 arrangedSubviews 병합
.compactMap { $0 as? UIButton } // UIButton만 남김
.forEach { $0.addTarget(self, action: #selector(buttonTapped(_:)), for: .touchUpInside) }
buttonStack 자체에 UIButton이 있다면?
만약 buttonStack에 UIStackView뿐 아니라 UIButton도 직접 추가되어 있다면, 코드에서 이를 처리하도록 flatMap 이전에 한 번 더 필터링해야 합니다.
calculatorView.buttonStack.arrangedSubviews
.flatMap { subview -> [UIView] in
if let stackView = subview as? UIStackView {
return stackView.arrangedSubviews
} else {
return [subview] // UIButton처럼 직접 추가된 경우 배열로 반환
}
}
.compactMap { $0 as? UIButton } // UIButton만 남김
.forEach { $0.addTarget(self, action: #selector(buttonTapped(_:)), for: .touchUpInside) }
어느 것이 더 좋은가?
간단하고 고정적인 UI라면 static 방식이 더 좋습니다. 반면, UI가 유동적이거나 상황에 따라 요소가 변해야 한다면 dynamic 방식을 선택하는 것이 효율적입니다.
displayText는 현재 값을 보여주는 역할을 합니다. private(set)을 사용하면 외부 코드에서 displayText를 읽을 수는 있지만 직접 변경할 수는 없습니다. 값의 변경은 클래스 내부의 로직에 의해서만 이루어져야 한다는 의도를 명확히 표현합니다.
class Calculator {
private(set) var displayText: String = "0"
func updateDisplayText(with newValue: String) {
displayText = newValue
}
}
let calculator = Calculator()
// 읽기 가능
print(calculator.displayText) // 출력: "0"
// 직접 변경 불가능
// calculator.displayText = "123" // 오류 발생: Cannot assign to property: 'displayText' setter is inaccessible
class Calculator {
private(set) var displayText: String = "0"
func updateDisplayText(with newValue: String) {
// 내부 로직으로만 값을 변경
displayText = newValue
}
}
let calculator = Calculator()
calculator.updateDisplayText(with: "123")
print(calculator.displayText) // 출력: "123"