diff --git a/Classes/BITHockeyHelper.h b/Classes/BITHockeyHelper.h index 9a7e1ecf5f..0f91ae1f63 100644 --- a/Classes/BITHockeyHelper.h +++ b/Classes/BITHockeyHelper.h @@ -48,8 +48,8 @@ NSString *bit_UUID(void); NSString *bit_appAnonID(void); BOOL bit_isPreiOS7Environment(void); -NSString *bit_validAppIconStringFromIcons(NSArray *icons); -NSString *bit_validAppIconFilename(NSBundle *bundle); +NSString *bit_validAppIconStringFromIcons(NSBundle *resourceBundle, NSArray *icons); +NSString *bit_validAppIconFilename(NSBundle *bundle, NSBundle *resourceBundle); /* UIImage helpers */ UIImage *bit_roundedCornerImage(UIImage *inputImage, NSInteger cornerSize, NSInteger borderSize); diff --git a/Classes/BITHockeyHelper.m b/Classes/BITHockeyHelper.m index 407bb14b20..5c954b4317 100644 --- a/Classes/BITHockeyHelper.m +++ b/Classes/BITHockeyHelper.m @@ -245,7 +245,7 @@ BOOL bit_isPreiOS7Environment(void) { @return NSString with the valid app icon or nil if none found */ -NSString *bit_validAppIconStringFromIcons(NSArray *icons) { +NSString *bit_validAppIconStringFromIcons(NSBundle *resourceBundle, NSArray *icons) { if (!icons) return nil; if (![icons isKindOfClass:[NSArray class]]) return nil; @@ -267,16 +267,29 @@ NSString *bit_validAppIconStringFromIcons(NSArray *icons) { for(NSString *icon in icons) { // Don't use imageNamed, otherwise unit tests won't find the fixture icon // and using imageWithContentsOfFile doesn't load @2x files with absolut paths (required in tests) - NSData *imgData = [[NSData alloc] initWithContentsOfFile:icon]; - UIImage *iconImage = [[UIImage alloc] initWithData:imgData]; + + NSString *iconPathExtension = ([[icon pathExtension] length] > 0) ? [icon pathExtension] : @"png"; + NSMutableArray *iconFilenameVariants = [NSMutableArray new]; - if (iconImage) { - if (iconImage.size.height == bestMatchHeight) { - return icon; - } else if (iconImage.size.height < bestMatchHeight && - iconImage.size.height > currentBestMatchHeight) { - currentBestMatchHeight = iconImage.size.height; - currentBestMatch = icon; + [iconFilenameVariants addObject:[icon stringByDeletingPathExtension]]; + [iconFilenameVariants addObject:[NSString stringWithFormat:@"%@@2x", [icon stringByDeletingPathExtension]]]; + + for (NSString *iconFilename in iconFilenameVariants) { + // this call already covers "~ipad" files + NSString *iconPath = [resourceBundle pathForResource:iconFilename ofType:iconPathExtension]; + + NSData *imgData = [[NSData alloc] initWithContentsOfFile:iconPath]; + + UIImage *iconImage = [[UIImage alloc] initWithData:imgData]; + + if (iconImage) { + if (iconImage.size.height == bestMatchHeight) { + return iconFilename; + } else if (iconImage.size.height < bestMatchHeight && + iconImage.size.height > currentBestMatchHeight) { + currentBestMatchHeight = iconImage.size.height; + currentBestMatch = iconFilename; + } } } } @@ -284,19 +297,19 @@ NSString *bit_validAppIconStringFromIcons(NSArray *icons) { return currentBestMatch; } -NSString *bit_validAppIconFilename(NSBundle *bundle) { +NSString *bit_validAppIconFilename(NSBundle *bundle, NSBundle *resourceBundle) { NSString *iconFilename = nil; NSArray *icons = nil; icons = [bundle objectForInfoDictionaryKey:@"CFBundleIconFiles"]; - iconFilename = bit_validAppIconStringFromIcons(icons); + iconFilename = bit_validAppIconStringFromIcons(resourceBundle, icons); if (!iconFilename) { icons = [bundle objectForInfoDictionaryKey:@"CFBundleIcons"]; if (icons && [icons isKindOfClass:[NSDictionary class]]) { icons = [icons valueForKeyPath:@"CFBundlePrimaryIcon.CFBundleIconFiles"]; } - iconFilename = bit_validAppIconStringFromIcons(icons); + iconFilename = bit_validAppIconStringFromIcons(resourceBundle, icons); } // we test iPad structure anyway and use it if we find a result and don't have another one yet @@ -305,7 +318,7 @@ NSString *bit_validAppIconFilename(NSBundle *bundle) { if (icons && [icons isKindOfClass:[NSDictionary class]]) { icons = [icons valueForKeyPath:@"CFBundlePrimaryIcon.CFBundleIconFiles"]; } - NSString *iPadIconFilename = bit_validAppIconStringFromIcons(icons); + NSString *iPadIconFilename = bit_validAppIconStringFromIcons(resourceBundle, icons); if (iPadIconFilename && !iconFilename) { iconFilename = iPadIconFilename; } @@ -314,12 +327,12 @@ NSString *bit_validAppIconFilename(NSBundle *bundle) { if (!iconFilename) { NSString *tempFilename = [bundle objectForInfoDictionaryKey:@"CFBundleIconFile"]; if (tempFilename) { - iconFilename = bit_validAppIconStringFromIcons(@[tempFilename]); + iconFilename = bit_validAppIconStringFromIcons(resourceBundle, @[tempFilename]); } } if (!iconFilename) { - iconFilename = bit_validAppIconStringFromIcons(@[@"Icon.png"]); + iconFilename = bit_validAppIconStringFromIcons(resourceBundle, @[@"Icon.png"]); } return iconFilename; diff --git a/Classes/BITUpdateViewController.m b/Classes/BITUpdateViewController.m index e75e22b19c..142112efaa 100644 --- a/Classes/BITUpdateViewController.m +++ b/Classes/BITUpdateViewController.m @@ -294,7 +294,7 @@ } [self updateAppStoreHeader]; - NSString *iconFilename = bit_validAppIconFilename([NSBundle mainBundle]); + NSString *iconFilename = bit_validAppIconFilename([NSBundle mainBundle], [NSBundle mainBundle]); if (iconFilename) { BOOL addGloss = YES; NSNumber *prerendered = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UIPrerenderedIcon"]; diff --git a/Support/HockeySDKTests/BITHockeyHelperTests.m b/Support/HockeySDKTests/BITHockeyHelperTests.m index 3cd800ade3..b6532d52d8 100644 --- a/Support/HockeySDKTests/BITHockeyHelperTests.m +++ b/Support/HockeySDKTests/BITHockeyHelperTests.m @@ -93,8 +93,9 @@ - (void)testValidAppIconFilename { NSString *resultString = nil; NSBundle *mockBundle = mock([NSBundle class]); - NSString *validIconPath = [[NSBundle bundleForClass:self.class] pathForResource:@"AppIcon" ofType:@"png"]; - NSString *validIconPath2x = [[NSBundle bundleForClass:self.class] pathForResource:@"AppIcon@2x" ofType:@"png"]; + NSBundle *resourceBundle = [NSBundle bundleForClass:self.class]; + NSString *validIconPath = @"AppIcon"; + NSString *validIconPath2x = @"AppIcon@2x"; // No valid icons defined at all [given([mockBundle objectForInfoDictionaryKey:@"CFBundleIconFiles"]) willReturn:nil]; @@ -102,7 +103,7 @@ [given([mockBundle objectForInfoDictionaryKey:@"CFBundleIcons~ipad"]) willReturn:nil]; [given([mockBundle objectForInfoDictionaryKey:@"CFBundleIconFile"]) willReturn:@"invalidFilename.png"]; - resultString = bit_validAppIconFilename(mockBundle); + resultString = bit_validAppIconFilename(mockBundle, resourceBundle); assertThat(resultString, nilValue()); // CFBundleIconFiles contains valid filenames @@ -111,7 +112,7 @@ [given([mockBundle objectForInfoDictionaryKey:@"CFBundleIcons~ipad"]) willReturn:nil]; [given([mockBundle objectForInfoDictionaryKey:@"CFBundleIconFile"]) willReturn:nil]; - resultString = bit_validAppIconFilename(mockBundle); + resultString = bit_validAppIconFilename(mockBundle, resourceBundle); assertThat(resultString, notNilValue()); // CFBundleIcons contains valid dictionary filenames @@ -126,7 +127,7 @@ [given([mockBundle objectForInfoDictionaryKey:@"CFBundleIcons~ipad"]) willReturn:@{@"CFBundlePrimaryIcon":@{@"CFBundleIconFiles":@[validIconPath, validIconPath2x]}}]; [given([mockBundle objectForInfoDictionaryKey:@"CFBundleIconFile"]) willReturn:nil]; - resultString = bit_validAppIconFilename(mockBundle); + resultString = bit_validAppIconFilename(mockBundle, resourceBundle); assertThat(resultString, notNilValue()); // CFBundleIcons contains valid filenames @@ -135,7 +136,7 @@ [given([mockBundle objectForInfoDictionaryKey:@"CFBundleIcons~ipad"]) willReturn:nil]; [given([mockBundle objectForInfoDictionaryKey:@"CFBundleIconFile"]) willReturn:nil]; - resultString = bit_validAppIconFilename(mockBundle); + resultString = bit_validAppIconFilename(mockBundle, resourceBundle); assertThat(resultString, notNilValue()); // CFBundleIcon contains valid filename @@ -144,7 +145,7 @@ [given([mockBundle objectForInfoDictionaryKey:@"CFBundleIcons~ipad"]) willReturn:nil]; [given([mockBundle objectForInfoDictionaryKey:@"CFBundleIconFile"]) willReturn:validIconPath]; - resultString = bit_validAppIconFilename(mockBundle); + resultString = bit_validAppIconFilename(mockBundle, resourceBundle); assertThat(resultString, notNilValue()); }