
프로퍼티 옵저버는 프로퍼티 값의 변화를 감지하고 반응할 수 있게 해주는 Swift의 강력한 기능입니다. 값이 변경되기 전과 후에 특정 코드를 실행할 수 있어 매우 유용합니다.
willSet: 값이 저장되기 직전에 호출didSet: 값이 저장된 직후에 호출class Temperature {
var celsius: Double = 0.0 {
willSet {
print("온도가 \(celsius)°C에서 \(newValue)°C로 변경될 예정입니다.")
}
didSet {
print("온도가 \(oldValue)°C에서 \(celsius)°C로 변경되었습니다.")
}
}
}
let temp = Temperature()
temp.celsius = 25.0
// 출력:
// 온도가 0.0°C에서 25.0°C로 변경될 예정입니다.
// 온도가 0.0°C에서 25.0°C로 변경되었습니다.
willSet - 값 변경 전class Counter {
var count: Int = 0 {
willSet(newCount) { // 매개변수명 직접 지정 가능
print("카운트가 \(count)에서 \(newCount)로 변경될 예정")
// 변경을 막을 수는 없지만, 준비 작업 가능
if newCount < 0 {
print("⚠️ 경고: 음수 값이 설정됩니다!")
}
}
}
}
let counter = Counter()
counter.count = 5 // willSet 호출
counter.count = -1 // 경고 메시지 출력
didSet - 값 변경 후class Player {
var score: Int = 0 {
didSet(previousScore) { // 매개변수명 직접 지정 가능
print("점수: \(previousScore) → \(score)")
// 값 변경 후 추가 로직 실행
if score > previousScore {
print("🎉 점수가 올랐습니다!")
}
// didSet에서 다시 값을 변경할 수도 있음
if score < 0 {
print("점수는 0보다 작을 수 없습니다.")
score = 0 // 재귀 호출되지 않음
}
}
}
}
let player = Player()
player.score = 100 // 점수 증가
player.score = -10 // 자동으로 0으로 수정됨
class ProgressView {
var progress: Double = 0.0 {
willSet {
// 유효성 검사
if newValue < 0.0 || newValue > 1.0 {
print("⚠️ 진행률은 0.0~1.0 사이여야 합니다.")
}
}
didSet {
// UI 업데이트
updateProgressBar()
// 완료 시 알림
if progress >= 1.0 {
print("✅ 작업이 완료되었습니다!")
notifyCompletion()
}
}
}
private func updateProgressBar() {
let percentage = Int(progress * 100)
print("진행률: \(percentage)%")
}
private func notifyCompletion() {
print("🔔 완료 알림 전송")
}
}
let progressView = ProgressView()
progressView.progress = 0.3 // 진행률: 30%
progressView.progress = 0.8 // 진행률: 80%
progressView.progress = 1.0 // 진행률: 100%, 완료 알림
struct User {
var email: String = "" {
willSet {
print("이메일 변경 시도: \(newValue)")
}
didSet {
// 자동 소문자 변환
if email != email.lowercased() {
email = email.lowercased()
}
// 유효성 검사
validateEmail()
}
}
private mutating func validateEmail() {
if !email.contains("@") {
print("⚠️ 유효하지 않은 이메일 형식입니다.")
} else {
print("✅ 이메일이 설정되었습니다: \(email)")
}
}
}
var user = User()
user.email = "JOHN@EXAMPLE.COM" // 자동으로 소문자로 변환
enum ConnectionState {
case disconnected, connecting, connected, error
}
class NetworkManager {
var connectionState: ConnectionState = .disconnected {
willSet {
print("연결 상태 변경: \(connectionState) → \(newValue)")
}
didSet {
handleStateChange(from: oldValue, to: connectionState)
}
}
private func handleStateChange(from oldState: ConnectionState, to newState: ConnectionState) {
switch newState {
case .connecting:
print("🔄 연결 중...")
case .connected:
print("✅ 연결 완료")
startHeartbeat()
case .disconnected:
print("❌ 연결 해제")
stopHeartbeat()
case .error:
print("🚨 연결 오류 발생")
attemptReconnection()
}
}
private func startHeartbeat() { print("💓 하트비트 시작") }
private func stopHeartbeat() { print("💔 하트비트 중지") }
private func attemptReconnection() { print("🔄 재연결 시도") }
}
let networkManager = NetworkManager()
networkManager.connectionState = .connecting
networkManager.connectionState = .connected
networkManager.connectionState = .error
class Example {
var value: Int = 10 { // 초기값 설정 시에는 옵저버 호출 안됨
didSet {
print("값이 변경됨: \(value)")
}
}
}
let example = Example() // didSet 호출되지 않음
example.value = 20 // didSet 호출됨
class Rectangle {
var width: Double = 0.0
var height: Double = 0.0
// ❌ 계산 프로퍼티에는 옵저버 사용 불가
var area: Double {
get { return width * height }
// willSet, didSet 사용 불가
}
}
didSet에서 같은 프로퍼티 수정 시 재귀 호출 안됨class SafeCounter {
var count: Int = 0 {
didSet {
if count < 0 {
count = 0 // 이 라인은 didSet을 다시 호출하지 않음
}
}
}
}
class DataManager {
// 저장 프로퍼티 + 옵저버
var rawData: String = "" {
didSet {
processedData = rawData.uppercased()
}
}
// 계산 프로퍼티
var processedData: String = ""
// 또는 계산 프로퍼티로만 처리
var alternativeProcessedData: String {
return rawData.uppercased()
}
}
willSet: 값 변경 직전 호출 (newValue 사용 가능)didSet: 값 변경 직후 호출 (oldValue 사용 가능)didSet에서 같은 프로퍼티 수정 시 재귀 호출 안됨프로퍼티 옵저버는 데이터의 변화를 자동으로 감지하고 적절히 반응할 수 있게 해주는 매우 유용한 기능입니다! 특히 MVVM 패턴이나 반응형 프로그래밍에서 핵심적인 역할을 합니다. 🚀