Alternate App Icons appear blurry within app despite using Apple's sample code

Viewed 30

I am looking to add alternate app icons to my iOS app but am encountering an issue where they are displaying as blurry in the app's view - but are crisp and clear when set as the app icon.

I am following Apple's Configuring Your App to Use Alternate App Icons developer documentation. Using Apple's Sample Code and running it in Xcode Preview and the Simulator both result in blurry app icons being shown in the view. The alternate app icon functionality works perfectly, and the app icon on the Home Screen appears correctly.

I closely adapted Apple's sample code within my own app and encounter the same blurry app icons - both in the Xcode Preview, Simulator, and on a real device.

See an example of the blurry app icons

I'm using Xcode 13.4.1 and targeting iOS 15.4.

I could add another image asset and just use that as the preview app icon - but I'd rather not bulk up the app with additional assets when each AppIcon has multiple sizes up to 1024x1024.


Below is a snippet of the key parts of the code from Apple's sample code for implementing alternate app icons - you can get it yourself here.

// Main View
struct IconChooser: View {
    @EnvironmentObject var model: Model

    var body: some View {
        let columns = [
            GridItem(),
            GridItem(),
            GridItem()
        ]

        VStack {
            HStack {
                Text("Select an icon:")
                    .font(.title)
                IconImage(icon: model.appIcon)
                    .frame(maxHeight: 100)
            }
            ScrollView {
                LazyVGrid(columns: columns) {
                    ForEach(Icon.allCases) { icon in
                        Button {
                            model.setAlternateAppIcon(icon: icon)
                        } label: {
                            IconImage(icon: icon)
                        }
                    }
                }
            }
        }
    }
}
// Sub-view for the individual app icon previews
struct IconImage: View {
    var icon: Icon

    var body: some View {
        Label {
            Text(icon.rawValue)
        } icon: {
            Image(uiImage: UIImage(named: icon.rawValue) ?? UIImage())
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(minHeight: 64)
                .cornerRadius(10)
                .shadow(radius: 10)
                .padding()
        }
            .labelStyle(.iconOnly)
    }
}
// Model
enum Icon: String, CaseIterable, Identifiable {
    case primary    = "AppIcon"
    case blue       = "AppIcon-Blue"
    case green      = "AppIcon-Green"
    case orange     = "AppIcon-Orange"
    case purple     = "AppIcon-Purple"
    case pink       = "AppIcon-Pink"
    case teal       = "AppIcon-Teal"
    case yellow     = "AppIcon-Yellow"

    var id: String { self.rawValue }
}

class Model: ObservableObject, Equatable {
    @Published var appIcon: Icon = .primary

    static func == (lhs: Model, rhs: Model) -> Bool {
        return lhs.appIcon == rhs.appIcon
    }

    /// Change the app icon.
    /// - Tag: setAlternateAppIcon
    func setAlternateAppIcon(icon: Icon) {
            // Set the icon name to nil to use the primary icon.
            let iconName: String? = (icon != .primary) ? icon.rawValue : nil

            // Avoid setting the name if the app already uses that icon.
            guard UIApplication.shared.alternateIconName != iconName else { return }

            UIApplication.shared.setAlternateIconName(iconName) { (error) in
                if let error = error {
                    print("Failed request to update the app’s icon: \(error)")
                }
            }

            appIcon = icon
    }

    /// Initializes the model with the current state of the app's icon.
    init() {
        let iconName = UIApplication.shared.alternateIconName

        if iconName == nil {
            appIcon = .primary
        } else {
            appIcon = Icon(rawValue: iconName!)!
        }
    }
}

0 Answers
Related