Reputation: 12559
Is there a way to get the current application icon in a cocoa-touch app? Thank you.
Upvotes: 36
Views: 27745
Reputation: 3883
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)
Upvotes: 5
Reputation: 3535
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?
Upvotes: 2
Reputation: 6668
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)
Upvotes: 7
Reputation: 27363
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
.
Upvotes: 34
Reputation: 36620
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.
Upvotes: 20
Reputation: 1844
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.
Upvotes: 3
Reputation: 12240
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
)
Upvotes: 14
Reputation: 1839
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.
Upvotes: 18
Reputation: 6886
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!)
Upvotes: 14
Reputation: 944
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
"[email protected]"//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!!
Upvotes: 10
Reputation: 11962
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];
}
}
Upvotes: 9