앱의 아이콘 이미지를 코드로 변경하는 방법에 대해 작성합니다.
요즘 크리스마스와 같은 특정 시즌에만 앱 아이콘 이미지를 변경하는 경우가 많습니다.
날짜에 맞춰 앱을 업데이트할 수 있다면 가장 좋겠지만,
현실적으로 어려우니 코드로 특정 시기에만 특정 이미지를 적용하는 방법에 대해 작성해보겠습니다.
먼저 일반적으로 사용할 앱 아이콘(appIcon)과,
특정 시기에만 사용할 앱 아이콘(specialIcon)을 png 파일로 Asset이 아닌 내부 파일로 추가해줍니다.
Info.plist에 사용하고자 하는 앱 아이콘들을 아래와 같이 작성해줍니다.
적용에 어려움이 있다면 아래의 Info.plist 코드를 참고해주세요.
<key>CFBundleIcons</key>
<dict>
<key>CFBundlePrimaryIcon</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>appIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
<key>CFBundleAlternateIcons</key>
<dict>
<key>XmasAppIcon</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>specialIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
<key>AppIcon</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>appIcon</string>
</array>
<key>UIPrerenderedIcon</key>
<false/>
</dict>
</dict>
</dict>
UIApplication.shared.setAlternateIconName("XmasAppIcon")
UIApplication.shared.setAlternateIconName(nil)
그런데, 저는 위 과정을 모두 따라해도 앱 아이콘이 변경되지 않았습니다. 🥲
여러가지 방법을 적용해보았는데 가장 먼저, 현재 앱 아이콘을 변경할 수 있는 상태인지를 확인해야합니다.
UIApplication.shared.supportsAlternateIcons
일반적으로 구글링을 통해 발견되는 원인은 아래 두 가지 인데
두 가지 모두 아니라면 이 것이 원인일 수도 있습니다.
그 다음 나타나는 View의 onAppear에서 앱 아이콘 변경을 시도하니 제대로 동작하였습니다 🎉!
그런데, 앱 아이콘은 변경되는건 좋은데 팝업까지는 조금 거창하다고 (저는) 생각했어요.
그래서 이 팝업창 띄우지 않고 앱 아이콘을 바꾸고자 한다면 아래 코드를 사용하면 됩니다.
func setIconWithoutAlert(_ appIconName: String) {
if let alternateIconName = UIApplication.shared.alternateIconName {
if alternateIconName == appIconName {
return
}
}
if UIApplication.shared.responds(to: #selector(getter: UIApplication.supportsAlternateIcons)) && UIApplication.shared.supportsAlternateIcons {
typealias setAlternateIconName = @convention(c) (NSObject, Selector, NSString, @escaping (NSError) -> ()) -> ()
let selectorString = "_setAlternateIconName:completionHandler:"
let selector = NSSelectorFromString(selectorString)
let imp = UIApplication.shared.method(for: selector)
let method = unsafeBitCast(imp, to: setAlternateIconName.self)
method(UIApplication.shared, selector, appIconName as NSString, { _ in })
} else {
}
}
따라서, 이름이 동일하면 바꾸지 않고 return 하고 동일하다면 바꿔줍니다.
한 가지 문제는, 여기서 unsafeBitCast가 apple에서 공식적으로 지원하는 함수는 아닌 것 같더라구요. 그래서 잘 판단해서 사용해야할 듯 싶습니다.
func changeAppIcon() {
if isChristmas() {
setIconWithoutAlert("XmasAppIcon")
} else {
setIconWithoutAlert("AppIcon")
}
}
요렇게 사용하면 됩니다.