32

Is there a way to get the current application icon in a cocoa-touch app? Thank you.

the Reverend
  • 12,305
  • 10
  • 66
  • 121

12 Answers12

31

Works for Swift 4.1 and extending it for Bundle.

extension Bundle {
    public var icon: UIImage? {
        if let icons = infoDictionary?["CFBundleIcons"] as? [String: Any],
            let primaryIcon = icons["CFBundlePrimaryIcon"] as? [String: Any],
            let iconFiles = primaryIcon["CFBundleIconFiles"] as? [String],
            let lastIcon = iconFiles.last {
            return UIImage(named: lastIcon)
        }
        return nil
    }
}

To use in an app, call Bundle.main.icon.

samwize
  • 25,675
  • 15
  • 141
  • 186
  • 5
    This gives me only the AppIcon60x60 (running on an iPhone7) or the AppIcon76x76 (running on an iPadPro 12.9" 4th-gen) simulator. Is there an other way to access the image at higher resolutions? I've have all sizes up to 1024pt in my assets. – themenace Jul 13 '20 at 13:18
  • Hmph. Pretty much just adapted my answer to an extension over 3+ years after my answer and was accepted instead of my answer. – Jeshua Lacock Jul 19 '20 at 07:49
  • 1
    This will still only give me the 60x60pt size on iPhone. The whole `icons` dict only returns the small sizes for me. Is there a way to access the 1024px App Store icon size? I’m using Xcode 14.3 and iOS 16. – alexkaessner Apr 26 '23 at 09:33
19

Here is a Swift 4.x && 3.x extension to UIApplication for obtaining the application icon. You can choose whether to get the smallest or largest icon based on the location of the icon path you pull from the iconFiles array.

extension UIApplication {
    var icon: UIImage? {
        guard let iconsDictionary = Bundle.main.infoDictionary?["CFBundleIcons"] as? NSDictionary,
            let primaryIconsDictionary = iconsDictionary["CFBundlePrimaryIcon"] as? NSDictionary,
            let iconFiles = primaryIconsDictionary["CFBundleIconFiles"] as? NSArray,
            // First will be smallest for the device class, last will be the largest for device class
            let lastIcon = iconFiles.lastObject as? String,
            let icon = UIImage(named: lastIcon) else {
                return nil
        }

        return icon
    }
}

To access the icon, call the following:

let icon = UIApplication.shared.icon

For bonus points, you could even make two vars to get the smallest and largest icon if your app needed it.

CodeBender
  • 35,668
  • 12
  • 125
  • 132
  • 1
    First line of Swift 3 code gives "Type 'Any' has no subscript members" – Crazor Sep 20 '16 at 16:30
  • @Crazor Thanks, that code initially worked when I tested in a beta build, but I saw the error you reported & updated the code to work. – CodeBender Sep 21 '16 at 02:18
18

The accepted answer did not work for me, I am using Xcode 5's Images.xcassets method of storing app icons. This modification worked for me:

UIImage *appIcon = [UIImage imageNamed: [[[[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIcons"] objectForKey:@"CFBundlePrimaryIcon"] objectForKey:@"CFBundleIconFiles"]  objectAtIndex:0]];

When in doubt, just explore the main bundle's infoDictionary using lldb.

Siegfoult
  • 1,844
  • 17
  • 19
  • 2
    A bit shorter: `UIImage *appIcon = [UIImage imageNamed:[[NSBundle mainBundle].infoDictionary[@"CFBundleIcons"][@"CFBundlePrimaryIcon"][@"CFBundleIconFiles"] firstObject]];` – pkamb Aug 20 '14 at 11:16
  • You should go for the lastObject to get a better quality. – nice_pink Aug 30 '18 at 08:52
14

I based my answer completely on moosgummi's, but returning a UIImage instead.

UIImage *appIcon = [UIImage imageNamed: [[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIconFiles"] objectAtIndex:0]];

The UIImage automatically selects the suitable version (normal, @2x, ~ipad, ~ipad@2x or any future suffix). (BTW, don't you just hate this stupid scheme for identifying versions of images? It was just getting out of hand. Thank god for Asset Catalogues!)

Community
  • 1
  • 1
Constantino Tsarouhas
  • 6,846
  • 6
  • 43
  • 54
  • 1
    I can confirm that the UIImage imageNamed does called the appropriate @2x file. As a note: The scale factor modifies the size of the image. – the Reverend Jun 12 '12 at 16:13
  • Actually the scheme does save a lot of work. The only thing I don't like is the size of the application with multiple images for different devices. Don't know if the App Store could be smart enough to deliver just the @2x images when retina is supported, etc. – the Reverend Jun 12 '12 at 16:19
14

If you use asset catalogues, then you can simply use:

UIImage* appIcon = [UIImage imageNamed:@"AppIcon60x60"];

Asset catalogues seem to standardize filenames for app icons.

Certainly if you need to list all app icons in your bundle you can look it up in CFBundleIconFiles branch of info dictionary.

Using KVC you can easily get that in a single line of code:

NSArray* allIcons = [[[NSBundle mainBundle] infoDictionary] valueForKeyPath:@"CFBundleIcons.CFBundlePrimaryIcon.CFBundleIconFiles"];

Resulting array will contain all app icon names available in your bundle. Any of these names can be used to retrieve icon using +[UIImage imageNamed:]

<__NSCFArray 0x15d54260>(
    AppIcon29x29,
    AppIcon40x40,
    AppIcon60x60
)
pronebird
  • 12,068
  • 5
  • 54
  • 82
10

This is how the icons is set inside the info.plist,

//try doing NSLog(@"%@",[[NSBundle mainBundle] infoDictionary]);

 CFBundleIcons =     {
        CFBundlePrimaryIcon =         {
            CFBundleIconFiles =             (
                "icon.png",//App icon added by you
                "icon@2x.png"//App icon in retina added by you
            );
            UIPrerenderedIcon = 1;
        };
    };

If you want to get the app icon use below code:

UIImage *appIcon = [UIImage imageNamed: [[[[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIcons"] objectForKey:@"CFBundlePrimaryIcon"] objectForKey:@"CFBundleIconFiles"] objectAtIndex:0]];

P.S: UIImage automatically picks the suitable icon for retina display.

I hope it helps!!

Sumit
  • 874
  • 9
  • 10
9

Thats easy, because the filename of the current icon is set in Info.plist:

NSString *filePath = [[NSString alloc] initWithString:[[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIconFiles"] objectAtIndex:0]];

If you want to pick the high-res version you should use:

NSString *filePath = nil;    
for (NSString *fileName in [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIconFiles"]) {
    if ([fileName rangeOfString:@"@2x"].location != NSNotFound) {
        filePath = [[NSString alloc] initWithString:fileName];
    }
}
dom
  • 11,894
  • 10
  • 51
  • 74
  • Seems that the code does not work well. I could not get icons, i do not know why :(. – timestee Apr 15 '12 at 11:43
  • Try `NSLog([NSBundle mainBundle] infoDictionary]);` to find out if there is a `CFBundleIconFiles` object. If not, there is something wrong with you app configuration. – dom Apr 16 '12 at 07:51
  • The call objectForKey returns id, sometime id's type really is NSString but not NSArray,perhaps this is the problem. – timestee Apr 16 '12 at 08:02
7

Because it took me a little while to work out, here is a working Swift solution.

let primaryIconsDictionary = NSBundle.mainBundle().infoDictionary?["CFBundleIcons"]?["CFBundlePrimaryIcon"] as? NSDictionary
let iconFiles = primaryIconsDictionary!["CFBundleIconFiles"] as NSArray
let lastIcon = iconFiles.lastObject as NSString //last seems to be largest, use first for smallest
let theIcon = UIImage(named: lastIcon)

let iconImageView = UIImageView(image: theIcon)
pkamb
  • 33,281
  • 23
  • 160
  • 191
Jeshua Lacock
  • 5,730
  • 1
  • 28
  • 58
3

If you're using Xamarin:

var iconNames = NSBundle.MainBundle.InfoDictionary.ValueForKeyPath((NSString)"CFBundleIcons.CFBundlePrimaryIcon.CFBundleIconFiles") as NSArray;
var name = iconNames.GetItem<NSString>(iconNames.Count - 1); //Grabs last item, call with 0 for the first item
var icon = UIImage.FromBundle(name);

Based on Andy's answer using the KVC method. Bit lengthy, but using KeyPath is better than chaining calls to ValueForKey.

Community
  • 1
  • 1
Russ
  • 1,786
  • 13
  • 17
3

Answer provided by @samwize is correct and for SwiftUI it would be:

Image(uiImage: Bundle.main.icon ?? UIImage())
Rufat Mirza
  • 1,425
  • 14
  • 20
3

A version of this answer worked best for me in SwiftUI because it allows you to choose the icon size you want (and 1x/2x/3x is chosen automatically by the system).

Image(uiImage: UIImage(named: "AppIcon60x60") ?? UIImage())
    .cornerRadius(10)
Robin Stewart
  • 3,147
  • 20
  • 29
2

Just for clarification this is what you get when you query the CFBundleIcon dictionary as per the examples above:

(key: "CFBundlePrimaryIcon", value: {
    CFBundleIconFiles =     (
        AppIcon60x60
    );
    CFBundleIconName = AppIcon;
})

Unfortunately there are only two values which are returned. One is the AppIcon60x60 on the iPhone Mini that I have, and the other, AppIcon is even smaller!

Anybody has another hint?

multitudes
  • 2,898
  • 2
  • 22
  • 29