Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
Tags
- tableView
- HIG
- RxCocoa
- combine
- 애니메이션
- Xcode
- clean architecture
- MVVM
- UITextView
- collectionview
- ribs
- rxswift
- 클린 코드
- swiftUI
- SWIFT
- map
- 리펙터링
- uitableview
- UICollectionView
- Clean Code
- Refactoring
- 리펙토링
- 리팩토링
- swift documentation
- 스위프트
- Observable
- uiscrollview
- ios
- Protocol
- Human interface guide
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] OptionSet으로 flag 리펙토링하기 (플래그 관리, Bool대신 bit 사용하기) 본문
iOS 응용 (swift)
[iOS - swift] OptionSet으로 flag 리펙토링하기 (플래그 관리, Bool대신 bit 사용하기)
jake-kim 2024. 9. 27. 01:24flag 관리하는 방법
- 유사한 성격의 flag를 관리할때 보통 아래처럼 작성
ex) 앱 유저 세팅에 관한 플래그를 관리하는 클래스
class UserSettings {
var isDarkModeEnabled: Bool
var isNotificationsEnabled: Bool
var isLocationServicesEnabled: Bool
var isAutoUpdateEnabled: Bool
var isPrivacyModeEnabled: Bool
var isSoundEnabled: Bool
var isVibrationEnabled: Bool
var isEmailUpdatesEnabled: Bool
var isTwoFactorAuthenticationEnabled: Bool
init(
isDarkModeEnabled: Bool = false,
isNotificationsEnabled: Bool = true,
isLocationServicesEnabled: Bool = false,
isAutoUpdateEnabled: Bool = true,
isPrivacyModeEnabled: Bool = false,
isSoundEnabled: Bool = true,
isVibrationEnabled: Bool = false,
isEmailUpdatesEnabled: Bool = true,
isTwoFactorAuthenticationEnabled: Bool = false
) {
self.isDarkModeEnabled = isDarkModeEnabled
self.isNotificationsEnabled = isNotificationsEnabled
self.isLocationServicesEnabled = isLocationServicesEnabled
self.isAutoUpdateEnabled = isAutoUpdateEnabled
self.isPrivacyModeEnabled = isPrivacyModeEnabled
self.isSoundEnabled = isSoundEnabled
self.isVibrationEnabled = isVibrationEnabled
self.isEmailUpdatesEnabled = isEmailUpdatesEnabled
self.isTwoFactorAuthenticationEnabled = isTwoFactorAuthenticationEnabled
}
}
- 위 형태의 문제점
- 1. 만약 "특정 플래그만 제외하고 다 초기화해줘"라는 의미의 clearAll(except:)라는 메서드를 구현할 경우 매우 복잡함
- 2. 메모리 효율성이 낮음
- 이것을 더욱 효율적으로 관리하고 싶은 경우?
- OptionSet을 활용
- OptionSet을 활용할때의 이점
- 0. 간결성
- 1. 비트 OR, AND 연산을 통해 충돌 없이 다중 상태 표현하기가 용이
- 2. 메모리 효율성
- 3. 비트 연산은 하드웨어적으로 매우 빠른 연산
* OptionSet 및 이점에 관한 구체적인 개념은 이전 포스팅 글 참고
OptionSet으로 리펙토링하기
- flag의 성격만 가지고 있으므로, 기존의 UserSettings 이름을 EnabledUserSettings로 바꾸고 여기에 속한 것들은 모두 enabled되어있다고 판단하여 사용
struct EnabledUserSettingsFlags: OptionSet {
let rawValue: Int
static let darkMode = EnabledUserSettingsFlags(rawValue: 1 << 0)
static let notifications = EnabledUserSettingsFlags(rawValue: 1 << 1)
static let locationServices = EnabledUserSettingsFlags(rawValue: 1 << 2)
static let autoUpdate = EnabledUserSettingsFlags(rawValue: 1 << 3)
static let privacyMode = EnabledUserSettingsFlags(rawValue: 1 << 4)
static let sound = EnabledUserSettingsFlags(rawValue: 1 << 5)
static let vibration = EnabledUserSettingsFlags(rawValue: 1 << 6)
static let emailUpdates = EnabledUserSettingsFlags(rawValue: 1 << 7)
static let twoFactorAuthentication = EnabledUserSettingsFlags(rawValue: 1 << 8)
static let all: EnabledUserSettingsFlags = [
.darkMode,
.notifications,
.locationServices,
.autoUpdate,
.privacyMode,
.sound,
.vibration,
.emailUpdates,
.twoFactorAuthentication
]
}
- 여기에 clearAll메서드도 구현에서도, 교집합을 사용하여 간결하게 표현이 가능
mutating func clearAll(except exceptions: EnabledUserSettingsFlags = []) {
self = self.intersection(exceptions)
}
- 사용하는 쪽)
var flag = EnabledUserSettingsFlags.all
print(flag.contains(.darkMode)) // true
flag.clearAll(except: .darkMode)
print(flag.contains(.darkMode)) // true
print(flag.contains(.notifications)) // false
- 활용할땐 이 객체를 싱글톤으로 만들고 플래그 값이 필요할 때 아래처럼 사용
if EnabledUserSettingsFlags.shared.contains(.darkMode) {
// darkmode에 관한 처리...
}
- OptionSet을 쓴 결과 얻은 점
- 0. 간결성
- 1. 비트 OR, AND 연산을 통해 충돌 없이 다중 상태 표현하기가 용이
- 2. 메모리 효율성
- 3. 비트 연산은 하드웨어적으로 매우 빠른 연산
* OptionSet 및 이점에 관한 구체적인 개념은 이전 포스팅 글 참고
'iOS 응용 (swift)' 카테고리의 다른 글
Comments