순서
  1. 기본 아이콘 및 추가 아이콘 이미지 파일 사이즈별로 준비
  2. 아이콘 변경 UI 만들기
  3. info.plist 파일 변경
  4. UI의 컨트롤러에 아이콘 변경 기능 부분 코드 추가

 

Swift(스위프트): 앱 아이콘 변경 기능 만들기

iOS 10 버전부터 아이폰/아이패드 홈 스크린의 앱 아이콘을 동적으로 변경할 수 있는 기능이 추가되었습니다. 이 기능을 추가하면 앱 사용자가 특정 앱을 기본 아이콘 외에 자신이 원하는 아이콘으로 변경할 수 있습니다.

대표적인 예로, 현재는 불가능하지만 예전에 인스타그램에서 깜짝 이벤트로 아이콘 변경 기능을 선보였던 적이 있었는데, 오늘 구현할 예제가 이것과 동일한 원리로 동작합니다.

 

이 예제는 기본 아이콘이 아래 그림과 같은 모양이며, 기본 아이콘 외에 Clock, Note, Space 3가지의 추가 아이콘을 가지고 있습니다. 변경 페이지에서 해당 아이콘을 클릭하면 홈 화면의 아이콘을 변경할 수 있습니다.

 

1: 기본 아이콘 및 추가 아이콘의 이미지를 준비

레티나 디스플레이를 사용하는 기기별로 사이즈가 대응이 되어야 하기 때문에 여러 px 사이즈의 아이콘 이미지를 미리 준비해야 합니다.

💡 appicon.co 라는 사이트를 이용하면 아이콘 이미지로부터 다양한 사이즈의 이미지를 편리하게 추출할 수 있습니다.

appicon.co 사이트를 통해 사이즈별로 이미지 파일이 준비된 모습

 

아이폰 전용 앱인 경우 두 가지 사이즈를 준비해야 하며, 아이패드까지 대응되는 경우에는 4가지 사이즈를 준비해야 합니다. 참고로 아이콘은 가로 세로 픽셀이 같은 정사각형 모양입니다.

이미지를 준비할 때 미리 파일 이름도 정리해 두는 편이 좋습니다. 아이콘이름@2x.png 이런 식으로 @를 기준으로 아이콘 이름, 대응 사이즈별로 파일 이름도 미리 대비합니다.

아이폰 전용

  • 120px – 아이콘이름@2x.png
  • 180px – 아이콘이름@3x.png

아이패드 겸용

  • 152px – 아이콘이름@2x~ipad.png
  • 167px – 아이콘이름@2x~ipad.png

이런식으로 변경하고자 하는 아이콘마다 사이즈에 맞게 준비합니다.

 

이렇게 각 사이즈의 아이콘 이미지를 준비했다면, Finder(탐색기)에서 파일을 프로젝트로 드래그하여 Xcode 프로젝트에 아이콘 파일을 추가합니다. 참고로 Assets 내에 추가하지 말고 프로젝트 내에 추가해야 하며, 폴더 생성시 Create Group을 선택합니다.

 

 

2: 아이콘 변경 UI 만들기

아이콘을 클릭하면 변경 기능이 동작할 수 있는 UI 를 만듭니다. 이벤트를 발생시킬 수 있는 한 다양한 방식으로 만들 수 있는데, 여기서는 컬렉션 뷰(Collection View)를 사용해서 만들었습니다.

컬렉션 뷰를 여기서 다루기에는 양이 많으므로 아래 링크글을 참고하세요.

import UIKit

class ViewController: UIViewController {
    
    let ICON_LIST = [
        "Default",
        "Clock",
        "Note",
        "Space",
    ]

    @IBOutlet weak var colViewAppIconSwitcher: UICollectionView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        colViewAppIconSwitcher.delegate = self
        colViewAppIconSwitcher.dataSource = self
        
        DispatchQueue.main.async {
            print(self.colViewAppIconSwitcher.frame)
        }
    }
}

extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        ICON_LIST.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "IconCell", for: indexPath)
        cell.layer.cornerRadius = cell.frame.height * 0.2237
        cell.backgroundView = UIImageView(image: UIImage(named: "\(ICON_LIST[indexPath.row]).png"))
        return cell
    }
    
    // 셀 클릭하면 아이콘 변경 - 잠시 후 구현
}

extension ViewController:  UICollectionViewDelegateFlowLayout {
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
        2
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let width = collectionView.frame.width
        let itemsPerRow: CGFloat = 4
        let widthPadding: CGFloat = 5 * (itemsPerRow + 1)
        let cellWidth = (width - widthPadding) / itemsPerRow
        
        return CGSize(width: cellWidth, height: cellWidth)
    }
}

 

3: info.plist 파일 변경

먼저 프로젝트의 info.plist를 마우스 오른쪽 클릭한 뒤, Open As > Source Code로 열면 XML 코드가 있는 에디터가 실행됩니다.

💡 반대로 원래 형태의 프로퍼티 리스트 에디터로 열고자 하는 경우 Property List 를 선택합니다.

 

다음 파일의 맨 끝부분을 찾습니다. </dict></plist> 이 부분의 바로 윗부분이 새로운 코드를 추가할 부분입니다.

 

<key>CFBundleIcons</key>
<dict>
    <key>CFBundleAlternateIcons</key>
    <dict>
        <key>코드에서_사용할_아이콘_이름_1</key>
        <dict>
            <key>CFBundleIconFiles</key>
            <array>
                <string>아이콘_파일이름(@앞까지)</string>
            </array>
            <key>UIPrerenderedIcon</key>
            <false/>
        </dict>
    </dict>
    <key>CFBundlePrimaryIcon</key>
    <dict>
        <key>CFBundleIconFiles</key>
        <array>
            <string></string>
        </array>
        <key>UIPrerenderedIcon</key>
        <false/>
    </dict>
</dict>

여기서 라인 5~13 부분이 커스텀 아이콘을 등록하는 부분이며,

  • 코드에서_사용할_아이콘_이름_1 이 부분에 아이콘 이름을 지정하고,
  • 아이콘_파일이름(@앞까지) 이 부분에 파일 이름을 등록합니다.
    예를 들어 파일 이름이 anotherIcon@2x.png인 경우 anotherIcon 여기까지만 입력합니다.

 

여러 개의 아이콘을 등록하고자 하는 경우 라인 5~13 부분을 여러 개 복사하여 사용하면 됩니다.

💡 info.plist 는 <key>태그쌍과 <dict>태그쌍이 페어를 이루어진 키-밸류 형태가 모인 딕셔너리 형태의 XML 파일이라는 점을 기억하면 편리하게 파일을 다룰 수 있습니다.

 

 

여기서 변경할 아이콘 종류는 기본 아이콘외에 Space, Note, Clock 3종류가 있으며 전부 반영하여 작성한 XML 코드는 다음과 같습니다.

<key>CFBundleIcons</key>
<dict>
    <key>CFBundleAlternateIcons</key>
    <dict>
        <key>Space</key>
        <dict>
            <key>CFBundleIconFiles</key>
            <array>
                <string>space</string>
            </array>
            <key>UIPrerenderedIcon</key>
            <false/>
        </dict>
        <key>Note</key>
        <dict>
            <key>CFBundleIconFiles</key>
            <array>
                <string>note</string>
            </array>
            <key>UIPrerenderedIcon</key>
            <false/>
        </dict>
        <key>Clock</key>
        <dict>
            <key>CFBundleIconFiles</key>
            <array>
                <string>clock</string>
            </array>
            <key>UIPrerenderedIcon</key>
            <false/>
        </dict>
    </dict>
    <key>CFBundlePrimaryIcon</key>
    <dict>
        <key>CFBundleIconFiles</key>
        <array>
            <string></string>
        </array>
        <key>UIPrerenderedIcon</key>
        <false/>
    </dict>
</dict>

Property LIst 에디터로 다시 열면 대략 다음과 같은 형태가 됩니다.

그리고 아이패드에서도 대응되게 하려면, 위에 작성된 XML 부분을 통째로 복사-붙여넣기 한 뒤, 맨 위의 키 이름을 CFBundleIcons~ipad 로 변경합니다.

<key>CFBundleIcons~ipad</key>
<!-- 이하 동일 -->

소스 코드

프로퍼티 리스트 에디터

 

4: 컨트롤러에 아이콘 변경 기능 부분 코드 추가

콜렉션 뷰에서 각 셀을 클릭하면 그 셀에 해당하는 아이콘으로 변경하면 됩니다. func collectionView(...~didSelectItemAt~...) 함수를 구현해 이벤트를 발생시킵니다.

앱 아이콘과 관련된 기능들은 크게 3가지가 있습니다.

  • UIApplication.shared.supportsAlternateIcons – 현재 기기에서 아이콘 변경 기능을 지원하는지 여부를 bool 값으로 반환합니다. 이 기능은 iOS 10 버전부터 등장했기 때문에 지금 시점에서 버전 문제가 발생할 가능성은 거의 없습니다.
  • UIApplication.shared.setAlternateIconName("아이콘이름", completionHandler) – info.plist에 등록한 아이콘 이름을 찾아 아이콘을 변경합니다. completionHandler는 에러가 발생했을 떄 주로 사용하고 성공적으로 변환된다면 사용하지 않아도 무방합니다.
    • 기본 아이콘을 사용하고자 한다면 아이콘 이름을 nil로 지정하면 됩니다.
  • UIApplication.shared.alternateIconName – 현재 사용되고 있는 아이콘 이름을 반환합니다.
    • nil이 반환되었다면 기본 아이콘을 사용중이라는 의미입니다.

 

// 셀 클릭하면 아이콘 변경
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    
    let appShared = UIApplication.shared
    if appShared.supportsAlternateIcons {
        
        guard indexPath.row != 0 else {
            appShared.setAlternateIconName(nil, completionHandler: nil)
            return
        }

        let iconName = ICON_LIST[indexPath.row]
        appShared.setAlternateIconName(iconName) { error in
            if let error = error {
                print(error.localizedDescription)
            }
        }
    }
}
  • guard indexPath.row != 0 else { ... }indexPath.row0이라면 기본 아이콘이고, 그 외라면 커스텀 아이콘입니다.
    • 기본 아이콘의 경우 아이콘 이름을 nil로 지정합니다.
  • indexPath.row 번째에 있는 ICON_LIST의 이름을 찾아 setAlternateIconName 메소드를 통해 아이콘을 변경합니다. 아이콘 이름은 반드시 info.plist 에 등록되어 있어야 합니다.

 

결과

 

주의사항

아이콘 변경 내용이 반영되지 않는다면 아래와 같이 시뮬레이터 또는 기기를 재부팅합니다.

JPG 파일의 경우 동작하지 않을 가능성이 매우 높으므로 아이콘 이미지 포맷은 PNG를 사용하는 것이 좋습니다.

 

문의 | 코멘트 또는 yoonbumtae@gmail.com


카테고리: Swift


0개의 댓글

답글 남기기

Avatar placeholder

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다