티스토리 뷰
App과 AppExtension (Today Extension, Widget Extension, Siri Extension 등..)은 UserDefaults를 공유하지 않습니다.
그 이유를 살펴볼게요
App Extension Programming Guide 를 보면 App과 App Extension의 관계가 나옵니다.
Extension은 App안에 있지만 두개는 각각 다른 container를 가지고 있습니다.
그래서 기본적으로 둘 사이의 데이터는 공유되지 않습니다.
그래서 UserDefaults는 공유되지 않습니다.
하지만 위의 그림처럼 shared container를 사용해서 UserDefaults를 공유할 수 있어요
[1] App Group 설정
Capability에 AppGroup를 추가하고 App과 Extension에 같은 App Group Identifier를 등록해주세요
(App Group Identifier는 bundle identifier 처럼 유니크한 값이에요)
[2] UserDefaults 공유 설정
UserDefaults.standard 말고
아래와 같은 extension을 만들고 UserDefaults.shared를 써주세요
appGroupId를 suitName으로 설정한 UserDefaults를 쓰겠다고 구현해준 것입니다.
extension UserDefaults {
static var shared: UserDefaults {
let appGroupId = "group.com.eunjin.githubprviewer"
return UserDefaults(suiteName: appGroupId)!
}
}
이제 App 또는 App Extension에서 shared UserDefaults에 새로 저장한 값은 App과 Extension에서 모두 쓸 수 있게 됩니다.
[3] Combinded UserDefaults
그러면 shared UserDefaults를 쓰기 전에 아래와 같이 App쪽에서 standard에 미리 저장했던 데이터는 어떻게 될까요..?!
UserDefaults.standard.setValue("테스트입니다", forKey: "test")
이렇게 출력해보면 nil이 나옵니다.
print(UserDefaults.shared.value(forKey: "test"))
아예 standard UserDefaults와 다른 새로운 UserDefaults를 만들었기 때문에
standard UserDefaults에 저장했던 데이터는 새로운 UserDefaults에 없는 것이 당연합니다.
그럴때는 addSuite 함수를 사용하여서 standard UserDefaults와 새로운 UserDefaults를 combine시킬 수 있습니다!+!
extension UserDefaults {
static var shared: UserDefaults {
let combined = UserDefaults.standard
let appGroupId = "group.com.eunjin.githubprviewer"
combined.addSuite(named: appGroupId)
return combined
}
}
print를 다시 해보면 이전에 저장했던 값이 잘 나오는 것을 알수있습니다.
print(UserDefaults.shared.value(forKey: "test"))
하지만 타겟을 Widget Extension으로 바꾸고 위젯쪽에서 출력해보면 nil이 나옵니다.
print(UserDefaults.shared.value(forKey: "test"))
왜냐면 UserDefaults.standard는 앱과 위젯에서 각각 다른 저장소이기 때문입니다.
위젯 extension으로 돌리면 UserDefaults.standard는 위젯 extension의 저장소를 말하는 것이고
여기에는 저 값이 없어서 nil이 나오는 게 맞습니다-!!
(아까 App쪽 UserDefaults.standard에 저장했으니까)
그래서 shared userdefaults 쓰기전, App쪽 standard userdefaults에 이미 저장되어있는 데이터를 쓰고 싶다면
이 코드로 다시 원복하고
extension UserDefaults {
static var shared: UserDefaults {
let appGroupId = "group.com.eunjin.githubprviewer"
return UserDefaults(suiteName: appGroupId)!
}
}
App쪽 Userdefaults standard에 저장된 값들을 모두 꺼내 shared userdefaults에 저장하면 됩니다-!!
UserDefaults.standard.dictionaryRepresentation().forEach { (key, value) in
UserDefaults.shared.set(value, forKey: key)
}
[ 더보면 좋을 것 ]
removeSuite(named:) 라는 함수도 있습니다-!
[ 유닛 테스트 타겟 ]
그렇담 앱 타겟과 UnitTest 타겟은 ?
1) UnitTest 타겟이 Hosting Application으로 앱 타켓을 포함하지 않는 경우:
UserDefaults 를 공유하지 않는다. (당연히 다른 번들이기 때문)
2) UnitTest 타겟이 Hosting Application으로 앱 타켓을 포함하는 경우:
테스트는 앱의 UserDefaults 를 READ 할 수 있지만 WRITE 할 수 없다.
('테스트만 앱을 알고 앱은 테스트를 알면 안된다.' 라는 방향에 맞는다.)
양방향이 아니기 때문에 UserDefaults 를 공유한다고 말하지는 않겠다.
자세히 말하면 다음과 같다. (관련 공식 문서를 못찾음. 내가 직접 테스트해본 결과임)
READ
1) 앱의 UserDefaults.standard 에 저장된 값을 테스트에서도 읽어올 수 있다.
2) 앱의 UserDefaults(suiteName:) 에 저장된 값을 테스트에서도 읽어올 수 있다. // test target에 appGroup 추가 안하고 app target에만 추가한 경우도.
WRITE
하지만 테스트에서 UserDefaults 값을 변경해도 app에서 찍어보면 반영되지 않는다.
------
참고로 번들 단위인 것 같다.
앱 타겟 - 유닛 테스트 타겟 과
Swift Pacakge 내의 Source - Tests 는 좀 다르다.
Swift Pacakge > 테스트에서 UserDefaults 값을 변경하면 source 쪽에도 반영되기 때문이다. (양방향)
Reference
www.swiftbysundell.com/articles/the-power-of-userdefaults-in-swift/
'🍏 > WidgetKit' 카테고리의 다른 글
[WidgetKit] IntentConfiguration으로 Edit Widget 기능을 추가하기 (0) | 2020.08.07 |
---|---|
[WidgetKit] 위젯만들기 (5) | 2020.07.28 |
[WidgetKit] TimeLineProvider와 WidgetCenter (2) | 2020.07.28 |
[Widget] Widget HIG 문서 간단 정리 (0) | 2020.07.20 |
- Total
- Today
- Yesterday
- ipad multitasking
- Flutter Clipboard
- 플러터 얼럿
- Python Type Hint
- Watch App for iOS App vs Watch App
- flutter 앱 출시
- Sketch 누끼
- 장고 Custom Management Command
- PencilKit
- flutter dynamic link
- Flutter Text Gradient
- ribs
- 플러터 싱글톤
- Django Heroku Scheduler
- Django Firebase Cloud Messaging
- drf custom error
- Django FCM
- Flutter getter setter
- flutter build mode
- Flutter 로딩
- 장고 URL querystring
- DRF APIException
- cocoapod
- Flutter Spacer
- SerializerMethodField
- flutter deep link
- Dart Factory
- METAL
- github actions
- 구글 Geocoding API
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |