맛동산이

UIKit) Dynamic App Icon 변경하기 본문

앱/Swift

UIKit) Dynamic App Icon 변경하기

진ddang 2024. 1. 1. 21:24

이벤트성으로 변경하고 appIcon을 변경하고 싶을때는 다음과 같은 순서로 진행하면 된다.

1. 이미지 추가하기

이미지 파일을 Assets가 아닌 파일로 추가를 해줘야한다.

copy items if needed를 체크하자~

Untitled.png

Untitled.png

2. Info.plist 변경하기

info.plist에서 새로운 항목을 추가한다.

icon files(iOS 5) 을 추가하고 해당 항목을보면 primary, newstand Icon가 있을텐데

primary는 앱 기본 icon의 이름으로 item0에 추가하면 된다.

다음은 CFBundleAlternateIcons를 딕셔너리로 생성한후

하위에 AppIcon을 딕셔너리

CFBundleIconFiles을 딕셔너리

Item(String)을 순서대로 만든다

Untitled.png

귀찮은 여러분들을 위해 소스파일도 준비완료!

<key>CFBundleIcons</key>
	<dict>
		<key>CFBundleAlternateIcons</key>
		<dict>
			<key>AppIcon</key>
			<array>
				<key>CFBundleIconFiles</key>
				<dict>
					<key>Item 0</key>
					<string>추가할 아이콘 이름</string>
				</array>
			</dict>
		</dict>
		<key>CFBundlePrimaryIcon</key>
		<dict>
			<key>CFBundleIconName</key>
			<string></string>
			<key>CFBundleIconFiles</key>
			<array>
				<string>기본아이콘이름</string>
			</array>
			<key>UIPrerenderedIcon</key>
			<false/>
		</dict>
		<key>UINewsstandIcon</key>
		<dict>
			<key>CFBundleIconFiles</key>
			<array>
				<string></string>
			</array>
			<key>UINewsstandBindingType</key>
			<string>UINewsstandBindingTypeMagazine</string>
			<key>UINewsstandBindingEdge</key>
			<string>UINewsstandBindingEdgeLeft</string>
		</dict>
	</dict>

3. 이제 코드로 적용을 해야한다.

코드로 적용하는 굉장히 단순한 방법이다.

UIApplication.shared.setAlternateIconName("AppIcon")

Untitled.png

이거 한줄이면 앱 아이콘이 변경된다.

하지만 문제가 있다.

바로 요런! 알람이 뜬다는것!

그것도 기본으로 추가되어있다.

그래서 이거를 없애는 코드를 찾아보니

func setIconWithoutAlert(_ appIcon: NIAppIconType) {
        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, appIcon.alternateIconName  as NSString, { _ in })
        }
    }

이코드를 사용하며 된다.

날짜 적용해서 사용해보기

특정 날짜를 지정해서 날짜기간동안 앱의 아이콘을 변경해주는 것이 가능한데, 방법은 다양하게 있지만, 네트워크를 통해서 변경해주거나, 할수있다.

네트워크를 통한 방법은 firebase의 remoteConfig를 추천한다.

하지만 여기에서는 그냥 static하게 사용하는 방법을 작성하겠다.

func setEventIconBetween(
	start: (year: Int, month: Int, day: Int),
	end: (year: Int, month: Int, day: Int),
	by iconName: String
){
	let startComponents = DayComponents(year: start.year, month: start.month, day: start.day)
	let endComponents = DayCopmponents(year: start.year, month: start.month, day: start.day + 1)
	guard let endDate = Calendar.current.date(from: endComponents) else {return}
	guard let startDate = Calendar.current.date(from: startComponents) else {return}
	let today = Date()
	if startDate.compare(today) == .orderedDescending {return setIcon(nil)}
	if endDate.compare(today) == .orderedAscending {return setIcon(nil}
	setIcon(iconName)
}

Desending의 경우에는 포함되고, Ascending의 경우에는 미포함이라 하루를 올려줘야하기때문에 day+1이다.

해당 기능이 앱이 실행시 변경되도록 하기 위해서는 앱라이프 사이클에 달아주면되는데

다양한 실험 결과 becomeActive에서만 실행된다. (혹은 다른 뷰에서 onAppear나, willAppear등등에서 해도됨) → 앱 라이프사이클에서는 becomeActive에서만 된다는 뜻임.

반응형