├── .gitignore ├── .travis.yml ├── AlternateIcons.xcodeproj ├── AltKitTests_Info.plist ├── AltKit_Info.plist ├── Files_Info.plist ├── Unbox_Info.plist ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ ├── AltKit.xcscheme │ ├── AlternateIcons.xcscheme │ └── xcschememanagement.plist ├── CHANGELOG.md ├── Demo ├── AlternateIcons.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata └── AlternateIcons │ ├── AlternateIcons.xcassets │ ├── Apple.appiconset │ │ ├── Contents.json │ │ ├── Icon-App-20x20@1x.png │ │ ├── Icon-App-20x20@2x-1.png │ │ ├── Icon-App-20x20@2x.png │ │ ├── Icon-App-20x20@3x.png │ │ ├── Icon-App-29x29@1x.png │ │ ├── Icon-App-29x29@2x-1.png │ │ ├── Icon-App-29x29@2x.png │ │ ├── Icon-App-29x29@3x.png │ │ ├── Icon-App-40x40@1x.png │ │ ├── Icon-App-40x40@2x-1.png │ │ ├── Icon-App-40x40@2x.png │ │ ├── Icon-App-40x40@3x.png │ │ ├── Icon-App-60x60@2x.png │ │ ├── Icon-App-60x60@3x.png │ │ ├── Icon-App-76x76@1x.png │ │ ├── Icon-App-76x76@2x.png │ │ ├── Icon-App-83.5x83.5@2x.png │ │ └── Icon-App-iTunes.png │ ├── Contents.json │ ├── Football.appiconset │ │ ├── Contents.json │ │ ├── Icon-App-20x20@1x.png │ │ ├── Icon-App-20x20@2x-1.png │ │ ├── Icon-App-20x20@2x.png │ │ ├── Icon-App-20x20@3x.png │ │ ├── Icon-App-29x29@1x.png │ │ ├── Icon-App-29x29@2x-1.png │ │ ├── Icon-App-29x29@2x.png │ │ ├── Icon-App-29x29@3x.png │ │ ├── Icon-App-40x40@1x.png │ │ ├── Icon-App-40x40@2x-1.png │ │ ├── Icon-App-40x40@2x.png │ │ ├── Icon-App-40x40@3x.png │ │ ├── Icon-App-60x60@2x.png │ │ ├── Icon-App-60x60@3x.png │ │ ├── Icon-App-76x76@1x.png │ │ ├── Icon-App-76x76@2x.png │ │ ├── Icon-App-83.5x83.5@2x.png │ │ └── Icon-App-iTunes.png │ ├── Panda.appiconset │ │ ├── Contents.json │ │ ├── Icon-App-20x20@1x.png │ │ ├── Icon-App-20x20@2x-1.png │ │ ├── Icon-App-20x20@2x.png │ │ ├── Icon-App-20x20@3x.png │ │ ├── Icon-App-29x29@1x.png │ │ ├── Icon-App-29x29@2x-1.png │ │ ├── Icon-App-29x29@2x.png │ │ ├── Icon-App-29x29@3x.png │ │ ├── Icon-App-40x40@1x.png │ │ ├── Icon-App-40x40@2x-1.png │ │ ├── Icon-App-40x40@2x.png │ │ ├── Icon-App-40x40@3x.png │ │ ├── Icon-App-60x60@2x.png │ │ ├── Icon-App-60x60@3x.png │ │ ├── Icon-App-76x76@1x.png │ │ ├── Icon-App-76x76@2x.png │ │ ├── Icon-App-83.5x83.5@2x.png │ │ └── Icon-App-iTunes.png │ └── Rocket.appiconset │ │ ├── Contents.json │ │ ├── Icon-App-20x20@1x.png │ │ ├── Icon-App-20x20@2x-1.png │ │ ├── Icon-App-20x20@2x.png │ │ ├── Icon-App-20x20@3x.png │ │ ├── Icon-App-29x29@1x.png │ │ ├── Icon-App-29x29@2x-1.png │ │ ├── Icon-App-29x29@2x.png │ │ ├── Icon-App-29x29@3x.png │ │ ├── Icon-App-40x40@1x.png │ │ ├── Icon-App-40x40@2x-1.png │ │ ├── Icon-App-40x40@2x.png │ │ ├── Icon-App-40x40@3x.png │ │ ├── Icon-App-60x60@2x.png │ │ ├── Icon-App-60x60@3x.png │ │ ├── Icon-App-76x76@1x.png │ │ ├── Icon-App-76x76@2x.png │ │ ├── Icon-App-83.5x83.5@2x.png │ │ └── Icon-App-iTunes.png │ ├── AppDelegate.swift │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── Icon-App-20x20@1x.png │ │ ├── Icon-App-20x20@2x-1.png │ │ ├── Icon-App-20x20@2x.png │ │ ├── Icon-App-20x20@3x.png │ │ ├── Icon-App-29x29@1x.png │ │ ├── Icon-App-29x29@2x-1.png │ │ ├── Icon-App-29x29@2x.png │ │ ├── Icon-App-29x29@3x.png │ │ ├── Icon-App-40x40@1x.png │ │ ├── Icon-App-40x40@2x-1.png │ │ ├── Icon-App-40x40@2x.png │ │ ├── Icon-App-40x40@3x.png │ │ ├── Icon-App-60x60@2x.png │ │ ├── Icon-App-60x60@3x.png │ │ ├── Icon-App-76x76@1x.png │ │ ├── Icon-App-76x76@2x.png │ │ ├── Icon-App-83.5x83.5@2x.png │ │ └── Icon-App-iTunes.png │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ └── ViewController.swift ├── LICENSE ├── Makefile ├── Package.swift ├── README.md ├── Sources ├── AltKit │ ├── AppIconSet.swift │ ├── AssetCatalog.swift │ ├── BundleIcon.swift │ ├── Error.swift │ ├── InfoPlist.swift │ ├── Script.swift │ └── Xcode.swift └── AlternateIcons │ └── main.swift ├── TestFixtures ├── AlternateInfo.plist ├── AppBundle │ ├── AppIconOld@2x.png │ └── Info.plist └── Images.xcassets │ ├── AppIcon.appiconset │ ├── Contents.json │ ├── Icon-20.png │ ├── Icon-20@2x.png │ ├── Icon-20@3x.png │ ├── Icon-60@2x.png │ ├── Icon-60@3x.png │ ├── Icon-72.png │ ├── Icon-72@2x.png │ ├── Icon-76.png │ ├── Icon-76@2x.png │ ├── Icon-83.5@2x.png │ ├── Icon-Small-1.png │ ├── Icon-Small-40.png │ ├── Icon-Small-40@2x-1.png │ ├── Icon-Small-40@2x.png │ ├── Icon-Small-40@3x.png │ ├── Icon-Small-50.png │ ├── Icon-Small-50@2x.png │ ├── Icon-Small.png │ ├── Icon-Small@2x-1.png │ ├── Icon-Small@2x.png │ ├── Icon-Small@3x.png │ ├── Icon.png │ └── Icon@2x.png │ ├── Contents.json │ ├── LaunchImage.launchimage │ ├── Contents.json │ ├── Default-568h@2x.png │ ├── Default-Landscape.png │ ├── Default-Landscape@2x.png │ ├── Default-Portrait.png │ ├── Default-Portrait@2x.png │ ├── Default-iOS7-568h@2x.png │ ├── Default-iOS7-Landscape.png │ ├── Default-iOS7-Landscape@2x.png │ ├── Default-iOS7-Portrait.png │ ├── Default-iOS7-Portrait@2x.png │ ├── Default-iOS7@2x.png │ ├── Default.png │ └── Default@2x.png │ ├── Light.appiconset │ ├── Contents.json │ ├── Icon-20.png │ ├── Icon-20@2x.png │ ├── Icon-20@3x.png │ ├── Icon-60@2x.png │ ├── Icon-60@3x.png │ ├── Icon-72.png │ ├── Icon-72@2x.png │ ├── Icon-76.png │ ├── Icon-76@2x.png │ ├── Icon-83.5@2x.png │ ├── Icon-Small-1.png │ ├── Icon-Small-40.png │ ├── Icon-Small-40@2x-1.png │ ├── Icon-Small-40@2x.png │ ├── Icon-Small-40@3x.png │ ├── Icon-Small-50.png │ ├── Icon-Small-50@2x.png │ ├── Icon-Small.png │ ├── Icon-Small@2x-1.png │ ├── Icon-Small@2x.png │ ├── Icon-Small@3x.png │ ├── Icon.png │ └── Icon@2x.png │ └── Sombre.appiconset │ ├── Contents.json │ ├── Icon-20.png │ ├── Icon-20@2x.png │ ├── Icon-20@3x.png │ ├── Icon-60@2x.png │ ├── Icon-60@3x.png │ ├── Icon-72.png │ ├── Icon-72@2x.png │ ├── Icon-76.png │ ├── Icon-76@2x.png │ ├── Icon-83.5@2x.png │ ├── Icon-Small-1.png │ ├── Icon-Small-40.png │ ├── Icon-Small-40@2x-1.png │ ├── Icon-Small-40@2x.png │ ├── Icon-Small-40@3x.png │ ├── Icon-Small-50.png │ ├── Icon-Small-50@2x.png │ ├── Icon-Small.png │ ├── Icon-Small@2x-1.png │ ├── Icon-Small@2x.png │ ├── Icon-Small@3x.png │ ├── Icon.png │ └── Icon@2x.png ├── Tests └── AltKitTests │ ├── AssetCatalogTests.swift │ ├── FailableTestCase.swift │ ├── InfoPlistTests.swift │ └── RunTests.swift └── install.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | .DS_Store 6 | 7 | ## Build generated 8 | build/ 9 | DerivedData/ 10 | 11 | ## Various settings 12 | *.pbxuser 13 | !default.pbxuser 14 | *.mode1v3 15 | !default.mode1v3 16 | *.mode2v3 17 | !default.mode2v3 18 | *.perspectivev3 19 | !default.perspectivev3 20 | xcuserdata/ 21 | 22 | ## Other 23 | *.moved-aside 24 | *.xccheckout 25 | *.xcscmblueprint 26 | 27 | ## Obj-C/Swift specific 28 | *.hmap 29 | *.ipa 30 | *.dSYM.zip 31 | *.dSYM 32 | 33 | ## Playgrounds 34 | timeline.xctimeline 35 | playground.xcworkspace 36 | 37 | # Swift Package Manager 38 | # 39 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 40 | # Packages/ 41 | Package.pins 42 | Package.resolved 43 | .build/ 44 | 45 | # CocoaPods 46 | # 47 | # We recommend against adding the Pods directory to your .gitignore. However 48 | # you should judge for yourself, the pros and cons are mentioned at: 49 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 50 | # 51 | # Pods/ 52 | 53 | # Carthage 54 | # 55 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 56 | # Carthage/Checkouts 57 | 58 | Carthage/Build 59 | 60 | # fastlane 61 | # 62 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 63 | # screenshots whenever they are needed. 64 | # For more information about the recommended setup visit: 65 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 66 | 67 | fastlane/report.xml 68 | fastlane/Preview.html 69 | fastlane/screenshots 70 | fastlane/test_output 71 | 72 | # Release 73 | *.release/ 74 | *.tar.gz 75 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | os: osx 2 | osx_image: xcode9 3 | language: objective-c 4 | 5 | script: 6 | - swift package resolve 7 | - xcodebuild clean test -scheme "AlternateIcons" -destination "arch=x86_64" 8 | 9 | before_deploy: 10 | - export RELEASE_NAME="alternate-icons-$TRAVIS_TAG.release" 11 | - make build 12 | - make release RELEASE_NAME="$RELEASE_NAME" 13 | 14 | deploy: 15 | skip_cleanup: true 16 | provider: releases 17 | api_key: 18 | secure: vQ9CLg4YEm30CQV64XQP2q26rKfYMayJW06qY8EJAkf+HWPf8wDsSwsH1V1LPcoXDWI9hy3Y4NwvKjpWoflByt82kjxBx4qPasILlve2V1PO/njbTL22SJJdd1FLYPCfLD9To5MXSvcbEZffQwk2MX4DfOSLOJjGR0Ku5dw+IVFsa5IxJRKXq7tmQTLlZUad221oBgdSKPWmWk1aTpw7a6E604/DCD/m31/fK2fnz0L9ZnCd/jUZkObWZ5jboJ0CAnhhVHnMSnl1u15LJCezXhmp+3XrqyhasYkigcescZSBoKz5/nk8S6QZZFIctkaDZdQjpou3MHnmeXnGWO7nREC/s3nQ59lAN05tf/MfxomI0QFEXku86N2KSkcc9LG0IA1wVMeaJeJDA7spk2wL/htjhlPTz6BUWZ5auGTC07KxHOXfuQHwaz64wpvLfdASnsQ7mA8txn54ZAenF+TwNGI4StdCFX4VyG6OwGSACHg3629NajyIFExEQaD0nb+Jbk4/S/P0jqSOPJr9xaAr0KP3bB7ASjMsK1kulZTqj3u9iGsJulhEoJwYdHihhg1pBNjUOekyrM2YzVyVTyCVqWc0mliutwhQbzP1YgJBUqr7b3tae7cpSXve6kXp8PqN5jKgjNTo62BgJipAJZWkCqwqbM7TZkfbb2m72zS+zVs= 19 | file: $RELEASE_NAME.tar.gz 20 | on: 21 | repo: alexaubry/alternate-icons 22 | tags: true 23 | -------------------------------------------------------------------------------- /AlternateIcons.xcodeproj/AltKitTests_Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CFBundleDevelopmentRegion 5 | en 6 | CFBundleExecutable 7 | $(EXECUTABLE_NAME) 8 | CFBundleIdentifier 9 | $(PRODUCT_BUNDLE_IDENTIFIER) 10 | CFBundleInfoDictionaryVersion 11 | 6.0 12 | CFBundleName 13 | $(PRODUCT_NAME) 14 | CFBundlePackageType 15 | BNDL 16 | CFBundleShortVersionString 17 | 1.0 18 | CFBundleSignature 19 | ???? 20 | CFBundleVersion 21 | $(CURRENT_PROJECT_VERSION) 22 | NSPrincipalClass 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /AlternateIcons.xcodeproj/AltKit_Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CFBundleDevelopmentRegion 5 | en 6 | CFBundleExecutable 7 | $(EXECUTABLE_NAME) 8 | CFBundleIdentifier 9 | $(PRODUCT_BUNDLE_IDENTIFIER) 10 | CFBundleInfoDictionaryVersion 11 | 6.0 12 | CFBundleName 13 | $(PRODUCT_NAME) 14 | CFBundlePackageType 15 | FMWK 16 | CFBundleShortVersionString 17 | 1.0 18 | CFBundleSignature 19 | ???? 20 | CFBundleVersion 21 | $(CURRENT_PROJECT_VERSION) 22 | NSPrincipalClass 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /AlternateIcons.xcodeproj/Files_Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CFBundleDevelopmentRegion 5 | en 6 | CFBundleExecutable 7 | $(EXECUTABLE_NAME) 8 | CFBundleIdentifier 9 | $(PRODUCT_BUNDLE_IDENTIFIER) 10 | CFBundleInfoDictionaryVersion 11 | 6.0 12 | CFBundleName 13 | $(PRODUCT_NAME) 14 | CFBundlePackageType 15 | FMWK 16 | CFBundleShortVersionString 17 | 1.0 18 | CFBundleSignature 19 | ???? 20 | CFBundleVersion 21 | $(CURRENT_PROJECT_VERSION) 22 | NSPrincipalClass 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /AlternateIcons.xcodeproj/Unbox_Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CFBundleDevelopmentRegion 5 | en 6 | CFBundleExecutable 7 | $(EXECUTABLE_NAME) 8 | CFBundleIdentifier 9 | $(PRODUCT_BUNDLE_IDENTIFIER) 10 | CFBundleInfoDictionaryVersion 11 | 6.0 12 | CFBundleName 13 | $(PRODUCT_NAME) 14 | CFBundlePackageType 15 | FMWK 16 | CFBundleShortVersionString 17 | 1.0 18 | CFBundleSignature 19 | ???? 20 | CFBundleVersion 21 | $(CURRENT_PROJECT_VERSION) 22 | NSPrincipalClass 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /AlternateIcons.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AlternateIcons.xcodeproj/xcshareddata/xcschemes/AltKit.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 34 | 40 | 41 | 42 | 43 | 44 | 50 | 51 | 52 | 53 | 57 | 58 | 62 | 63 | 67 | 68 | 69 | 70 | 71 | 72 | 82 | 83 | 89 | 90 | 91 | 92 | 93 | 94 | 100 | 101 | 107 | 108 | 109 | 110 | 112 | 113 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /AlternateIcons.xcodeproj/xcshareddata/xcschemes/AlternateIcons.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 34 | 40 | 41 | 42 | 43 | 44 | 50 | 51 | 52 | 53 | 57 | 58 | 62 | 63 | 67 | 68 | 69 | 70 | 71 | 72 | 82 | 84 | 90 | 91 | 92 | 93 | 94 | 95 | 101 | 103 | 109 | 110 | 111 | 112 | 114 | 115 | 118 | 119 | 120 | -------------------------------------------------------------------------------- /AlternateIcons.xcodeproj/xcshareddata/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SchemeUserState 5 | 6 | AlternateIcons-Package.xcscheme 7 | 8 | 9 | SuppressBuildableAutocreation 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # AlternateIcons Release History 2 | 3 | ## [2017-09-20] 🔖 v2.0.0 4 | 5 | - Support new Xcode 9 alternate icons workflow 6 | - Add demo project 7 | - Fix iTunes Connect submission error 8 | - Fix iPhone / iPad Retina file names 9 | - Migrate to Swift 4 10 | 11 | ## [2017-06-23] 🔖 v1.1.0 12 | 13 | - Fix an issue that stopped embedding when a variant of an icon set was not filled (#1) 14 | - Improve deleted icons cleanup: faster and less complex 15 | - Improve error handling 16 | - Improve README 17 | 18 | ## [2017-06-23] 🔖 v1.0.1 19 | 20 | - Fix Travis Automated Deploy 21 | 22 | ## [2017-06-23] 🔖 v1.0.0 23 | 24 | - Initial Release 25 | -------------------------------------------------------------------------------- /Demo/AlternateIcons.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 55AB8CA31F71186B00FE26BE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55AB8CA21F71186B00FE26BE /* AppDelegate.swift */; }; 11 | 55AB8CA51F71186B00FE26BE /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55AB8CA41F71186B00FE26BE /* ViewController.swift */; }; 12 | 55AB8CA81F71186B00FE26BE /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 55AB8CA61F71186B00FE26BE /* Main.storyboard */; }; 13 | 55AB8CAA1F71186B00FE26BE /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 55AB8CA91F71186B00FE26BE /* Assets.xcassets */; }; 14 | 55AB8CAD1F71186B00FE26BE /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 55AB8CAB1F71186B00FE26BE /* LaunchScreen.storyboard */; }; 15 | 55AB8CB51F7118AF00FE26BE /* AlternateIcons.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 55AB8CB41F7118AF00FE26BE /* AlternateIcons.xcassets */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXFileReference section */ 19 | 55AB8C9F1F71186B00FE26BE /* AlternateIcons.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AlternateIcons.app; sourceTree = BUILT_PRODUCTS_DIR; }; 20 | 55AB8CA21F71186B00FE26BE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 21 | 55AB8CA41F71186B00FE26BE /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 22 | 55AB8CA71F71186B00FE26BE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 23 | 55AB8CA91F71186B00FE26BE /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 24 | 55AB8CAC1F71186B00FE26BE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 25 | 55AB8CAE1F71186B00FE26BE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 26 | 55AB8CB41F7118AF00FE26BE /* AlternateIcons.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = AlternateIcons.xcassets; sourceTree = ""; }; 27 | /* End PBXFileReference section */ 28 | 29 | /* Begin PBXFrameworksBuildPhase section */ 30 | 55AB8C9C1F71186B00FE26BE /* Frameworks */ = { 31 | isa = PBXFrameworksBuildPhase; 32 | buildActionMask = 2147483647; 33 | files = ( 34 | ); 35 | runOnlyForDeploymentPostprocessing = 0; 36 | }; 37 | /* End PBXFrameworksBuildPhase section */ 38 | 39 | /* Begin PBXGroup section */ 40 | 55AB8C961F71186B00FE26BE = { 41 | isa = PBXGroup; 42 | children = ( 43 | 55AB8CA11F71186B00FE26BE /* AlternateIcons */, 44 | 55AB8CA01F71186B00FE26BE /* Products */, 45 | ); 46 | sourceTree = ""; 47 | }; 48 | 55AB8CA01F71186B00FE26BE /* Products */ = { 49 | isa = PBXGroup; 50 | children = ( 51 | 55AB8C9F1F71186B00FE26BE /* AlternateIcons.app */, 52 | ); 53 | name = Products; 54 | sourceTree = ""; 55 | }; 56 | 55AB8CA11F71186B00FE26BE /* AlternateIcons */ = { 57 | isa = PBXGroup; 58 | children = ( 59 | 55AB8CA21F71186B00FE26BE /* AppDelegate.swift */, 60 | 55AB8CA41F71186B00FE26BE /* ViewController.swift */, 61 | 55AB8CA61F71186B00FE26BE /* Main.storyboard */, 62 | 55AB8CA91F71186B00FE26BE /* Assets.xcassets */, 63 | 55AB8CAB1F71186B00FE26BE /* LaunchScreen.storyboard */, 64 | 55AB8CAE1F71186B00FE26BE /* Info.plist */, 65 | 55AB8CB41F7118AF00FE26BE /* AlternateIcons.xcassets */, 66 | ); 67 | path = AlternateIcons; 68 | sourceTree = ""; 69 | }; 70 | /* End PBXGroup section */ 71 | 72 | /* Begin PBXNativeTarget section */ 73 | 55AB8C9E1F71186B00FE26BE /* AlternateIcons */ = { 74 | isa = PBXNativeTarget; 75 | buildConfigurationList = 55AB8CB11F71186B00FE26BE /* Build configuration list for PBXNativeTarget "AlternateIcons" */; 76 | buildPhases = ( 77 | 55AB8C9B1F71186B00FE26BE /* Sources */, 78 | 55AB8C9C1F71186B00FE26BE /* Frameworks */, 79 | 55AB8C9D1F71186B00FE26BE /* Resources */, 80 | 55AB8CB61F7118BA00FE26BE /* Embed Alternate Icons */, 81 | ); 82 | buildRules = ( 83 | ); 84 | dependencies = ( 85 | ); 86 | name = AlternateIcons; 87 | productName = AlternateIcons; 88 | productReference = 55AB8C9F1F71186B00FE26BE /* AlternateIcons.app */; 89 | productType = "com.apple.product-type.application"; 90 | }; 91 | /* End PBXNativeTarget section */ 92 | 93 | /* Begin PBXProject section */ 94 | 55AB8C971F71186B00FE26BE /* Project object */ = { 95 | isa = PBXProject; 96 | attributes = { 97 | LastSwiftUpdateCheck = 0900; 98 | LastUpgradeCheck = 0900; 99 | ORGANIZATIONNAME = "AURA Media"; 100 | TargetAttributes = { 101 | 55AB8C9E1F71186B00FE26BE = { 102 | CreatedOnToolsVersion = 9.0; 103 | ProvisioningStyle = Automatic; 104 | }; 105 | }; 106 | }; 107 | buildConfigurationList = 55AB8C9A1F71186B00FE26BE /* Build configuration list for PBXProject "AlternateIcons" */; 108 | compatibilityVersion = "Xcode 8.0"; 109 | developmentRegion = en; 110 | hasScannedForEncodings = 0; 111 | knownRegions = ( 112 | en, 113 | Base, 114 | ); 115 | mainGroup = 55AB8C961F71186B00FE26BE; 116 | productRefGroup = 55AB8CA01F71186B00FE26BE /* Products */; 117 | projectDirPath = ""; 118 | projectRoot = ""; 119 | targets = ( 120 | 55AB8C9E1F71186B00FE26BE /* AlternateIcons */, 121 | ); 122 | }; 123 | /* End PBXProject section */ 124 | 125 | /* Begin PBXResourcesBuildPhase section */ 126 | 55AB8C9D1F71186B00FE26BE /* Resources */ = { 127 | isa = PBXResourcesBuildPhase; 128 | buildActionMask = 2147483647; 129 | files = ( 130 | 55AB8CAD1F71186B00FE26BE /* LaunchScreen.storyboard in Resources */, 131 | 55AB8CAA1F71186B00FE26BE /* Assets.xcassets in Resources */, 132 | 55AB8CA81F71186B00FE26BE /* Main.storyboard in Resources */, 133 | 55AB8CB51F7118AF00FE26BE /* AlternateIcons.xcassets in Resources */, 134 | ); 135 | runOnlyForDeploymentPostprocessing = 0; 136 | }; 137 | /* End PBXResourcesBuildPhase section */ 138 | 139 | /* Begin PBXShellScriptBuildPhase section */ 140 | 55AB8CB61F7118BA00FE26BE /* Embed Alternate Icons */ = { 141 | isa = PBXShellScriptBuildPhase; 142 | buildActionMask = 2147483647; 143 | files = ( 144 | ); 145 | inputPaths = ( 146 | "$(PROJECT_DIR)/AlternateIcons/AlternateIcons.xcassets", 147 | ); 148 | name = "Embed Alternate Icons"; 149 | outputPaths = ( 150 | ); 151 | runOnlyForDeploymentPostprocessing = 0; 152 | shellPath = /bin/sh; 153 | shellScript = "embed-alternate-icons"; 154 | }; 155 | /* End PBXShellScriptBuildPhase section */ 156 | 157 | /* Begin PBXSourcesBuildPhase section */ 158 | 55AB8C9B1F71186B00FE26BE /* Sources */ = { 159 | isa = PBXSourcesBuildPhase; 160 | buildActionMask = 2147483647; 161 | files = ( 162 | 55AB8CA51F71186B00FE26BE /* ViewController.swift in Sources */, 163 | 55AB8CA31F71186B00FE26BE /* AppDelegate.swift in Sources */, 164 | ); 165 | runOnlyForDeploymentPostprocessing = 0; 166 | }; 167 | /* End PBXSourcesBuildPhase section */ 168 | 169 | /* Begin PBXVariantGroup section */ 170 | 55AB8CA61F71186B00FE26BE /* Main.storyboard */ = { 171 | isa = PBXVariantGroup; 172 | children = ( 173 | 55AB8CA71F71186B00FE26BE /* Base */, 174 | ); 175 | name = Main.storyboard; 176 | sourceTree = ""; 177 | }; 178 | 55AB8CAB1F71186B00FE26BE /* LaunchScreen.storyboard */ = { 179 | isa = PBXVariantGroup; 180 | children = ( 181 | 55AB8CAC1F71186B00FE26BE /* Base */, 182 | ); 183 | name = LaunchScreen.storyboard; 184 | sourceTree = ""; 185 | }; 186 | /* End PBXVariantGroup section */ 187 | 188 | /* Begin XCBuildConfiguration section */ 189 | 55AB8CAF1F71186B00FE26BE /* Debug */ = { 190 | isa = XCBuildConfiguration; 191 | buildSettings = { 192 | ALWAYS_SEARCH_USER_PATHS = NO; 193 | CLANG_ANALYZER_NONNULL = YES; 194 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 195 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 196 | CLANG_CXX_LIBRARY = "libc++"; 197 | CLANG_ENABLE_MODULES = YES; 198 | CLANG_ENABLE_OBJC_ARC = YES; 199 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 200 | CLANG_WARN_BOOL_CONVERSION = YES; 201 | CLANG_WARN_COMMA = YES; 202 | CLANG_WARN_CONSTANT_CONVERSION = YES; 203 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 204 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 205 | CLANG_WARN_EMPTY_BODY = YES; 206 | CLANG_WARN_ENUM_CONVERSION = YES; 207 | CLANG_WARN_INFINITE_RECURSION = YES; 208 | CLANG_WARN_INT_CONVERSION = YES; 209 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 210 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 211 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 212 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 213 | CLANG_WARN_STRICT_PROTOTYPES = YES; 214 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 215 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 216 | CLANG_WARN_UNREACHABLE_CODE = YES; 217 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 218 | CODE_SIGN_IDENTITY = "iPhone Developer"; 219 | COPY_PHASE_STRIP = NO; 220 | DEBUG_INFORMATION_FORMAT = dwarf; 221 | ENABLE_STRICT_OBJC_MSGSEND = YES; 222 | ENABLE_TESTABILITY = YES; 223 | GCC_C_LANGUAGE_STANDARD = gnu11; 224 | GCC_DYNAMIC_NO_PIC = NO; 225 | GCC_NO_COMMON_BLOCKS = YES; 226 | GCC_OPTIMIZATION_LEVEL = 0; 227 | GCC_PREPROCESSOR_DEFINITIONS = ( 228 | "DEBUG=1", 229 | "$(inherited)", 230 | ); 231 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 232 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 233 | GCC_WARN_UNDECLARED_SELECTOR = YES; 234 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 235 | GCC_WARN_UNUSED_FUNCTION = YES; 236 | GCC_WARN_UNUSED_VARIABLE = YES; 237 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 238 | MTL_ENABLE_DEBUG_INFO = YES; 239 | ONLY_ACTIVE_ARCH = YES; 240 | SDKROOT = iphoneos; 241 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 242 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 243 | }; 244 | name = Debug; 245 | }; 246 | 55AB8CB01F71186B00FE26BE /* Release */ = { 247 | isa = XCBuildConfiguration; 248 | buildSettings = { 249 | ALWAYS_SEARCH_USER_PATHS = NO; 250 | CLANG_ANALYZER_NONNULL = YES; 251 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 252 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 253 | CLANG_CXX_LIBRARY = "libc++"; 254 | CLANG_ENABLE_MODULES = YES; 255 | CLANG_ENABLE_OBJC_ARC = YES; 256 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 257 | CLANG_WARN_BOOL_CONVERSION = YES; 258 | CLANG_WARN_COMMA = YES; 259 | CLANG_WARN_CONSTANT_CONVERSION = YES; 260 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 261 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 262 | CLANG_WARN_EMPTY_BODY = YES; 263 | CLANG_WARN_ENUM_CONVERSION = YES; 264 | CLANG_WARN_INFINITE_RECURSION = YES; 265 | CLANG_WARN_INT_CONVERSION = YES; 266 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 267 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 268 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 269 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 270 | CLANG_WARN_STRICT_PROTOTYPES = YES; 271 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 272 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 273 | CLANG_WARN_UNREACHABLE_CODE = YES; 274 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 275 | CODE_SIGN_IDENTITY = "iPhone Developer"; 276 | COPY_PHASE_STRIP = NO; 277 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 278 | ENABLE_NS_ASSERTIONS = NO; 279 | ENABLE_STRICT_OBJC_MSGSEND = YES; 280 | GCC_C_LANGUAGE_STANDARD = gnu11; 281 | GCC_NO_COMMON_BLOCKS = YES; 282 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 283 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 284 | GCC_WARN_UNDECLARED_SELECTOR = YES; 285 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 286 | GCC_WARN_UNUSED_FUNCTION = YES; 287 | GCC_WARN_UNUSED_VARIABLE = YES; 288 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 289 | MTL_ENABLE_DEBUG_INFO = NO; 290 | SDKROOT = iphoneos; 291 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 292 | VALIDATE_PRODUCT = YES; 293 | }; 294 | name = Release; 295 | }; 296 | 55AB8CB21F71186B00FE26BE /* Debug */ = { 297 | isa = XCBuildConfiguration; 298 | buildSettings = { 299 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 300 | CODE_SIGN_STYLE = Automatic; 301 | DEVELOPMENT_TEAM = 75E8K39Z38; 302 | INFOPLIST_FILE = AlternateIcons/Info.plist; 303 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 304 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 305 | PRODUCT_BUNDLE_IDENTIFIER = com.AlternateIcons.AlternateIcons; 306 | PRODUCT_NAME = "$(TARGET_NAME)"; 307 | SWIFT_VERSION = 4.0; 308 | TARGETED_DEVICE_FAMILY = "1,2"; 309 | }; 310 | name = Debug; 311 | }; 312 | 55AB8CB31F71186B00FE26BE /* Release */ = { 313 | isa = XCBuildConfiguration; 314 | buildSettings = { 315 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 316 | CODE_SIGN_STYLE = Automatic; 317 | DEVELOPMENT_TEAM = 75E8K39Z38; 318 | INFOPLIST_FILE = AlternateIcons/Info.plist; 319 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 320 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 321 | PRODUCT_BUNDLE_IDENTIFIER = com.AlternateIcons.AlternateIcons; 322 | PRODUCT_NAME = "$(TARGET_NAME)"; 323 | SWIFT_VERSION = 4.0; 324 | TARGETED_DEVICE_FAMILY = "1,2"; 325 | }; 326 | name = Release; 327 | }; 328 | /* End XCBuildConfiguration section */ 329 | 330 | /* Begin XCConfigurationList section */ 331 | 55AB8C9A1F71186B00FE26BE /* Build configuration list for PBXProject "AlternateIcons" */ = { 332 | isa = XCConfigurationList; 333 | buildConfigurations = ( 334 | 55AB8CAF1F71186B00FE26BE /* Debug */, 335 | 55AB8CB01F71186B00FE26BE /* Release */, 336 | ); 337 | defaultConfigurationIsVisible = 0; 338 | defaultConfigurationName = Release; 339 | }; 340 | 55AB8CB11F71186B00FE26BE /* Build configuration list for PBXNativeTarget "AlternateIcons" */ = { 341 | isa = XCConfigurationList; 342 | buildConfigurations = ( 343 | 55AB8CB21F71186B00FE26BE /* Debug */, 344 | 55AB8CB31F71186B00FE26BE /* Release */, 345 | ); 346 | defaultConfigurationIsVisible = 0; 347 | defaultConfigurationName = Release; 348 | }; 349 | /* End XCConfigurationList section */ 350 | }; 351 | rootObject = 55AB8C971F71186B00FE26BE /* Project object */; 352 | } 353 | -------------------------------------------------------------------------------- /Demo/AlternateIcons.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "40x40", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-40x40@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@3x.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "60x60", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-60x60@2x.png", 43 | "scale" : "2x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@3x.png", 49 | "scale" : "3x" 50 | }, 51 | { 52 | "size" : "20x20", 53 | "idiom" : "ipad", 54 | "filename" : "Icon-App-20x20@1x.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@2x-1.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "29x29", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-29x29@1x.png", 67 | "scale" : "1x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@2x-1.png", 73 | "scale" : "2x" 74 | }, 75 | { 76 | "size" : "40x40", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-40x40@1x.png", 79 | "scale" : "1x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@2x-1.png", 85 | "scale" : "2x" 86 | }, 87 | { 88 | "size" : "76x76", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-76x76@1x.png", 91 | "scale" : "1x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@2x.png", 97 | "scale" : "2x" 98 | }, 99 | { 100 | "size" : "83.5x83.5", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-83.5x83.5@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "1024x1024", 107 | "idiom" : "ios-marketing", 108 | "filename" : "Icon-App-iTunes.png", 109 | "scale" : "1x" 110 | } 111 | ], 112 | "info" : { 113 | "version" : 1, 114 | "author" : "xcode" 115 | } 116 | } -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-20x20@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-20x20@2x-1.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-29x29@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-29x29@2x-1.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-40x40@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-40x40@2x-1.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-iTunes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Apple.appiconset/Icon-App-iTunes.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "40x40", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-40x40@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@3x.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "60x60", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-60x60@2x.png", 43 | "scale" : "2x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@3x.png", 49 | "scale" : "3x" 50 | }, 51 | { 52 | "size" : "20x20", 53 | "idiom" : "ipad", 54 | "filename" : "Icon-App-20x20@1x.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@2x-1.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "29x29", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-29x29@1x.png", 67 | "scale" : "1x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@2x-1.png", 73 | "scale" : "2x" 74 | }, 75 | { 76 | "size" : "40x40", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-40x40@1x.png", 79 | "scale" : "1x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@2x-1.png", 85 | "scale" : "2x" 86 | }, 87 | { 88 | "size" : "76x76", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-76x76@1x.png", 91 | "scale" : "1x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@2x.png", 97 | "scale" : "2x" 98 | }, 99 | { 100 | "size" : "83.5x83.5", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-83.5x83.5@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "1024x1024", 107 | "idiom" : "ios-marketing", 108 | "filename" : "Icon-App-iTunes.png", 109 | "scale" : "1x" 110 | } 111 | ], 112 | "info" : { 113 | "version" : 1, 114 | "author" : "xcode" 115 | } 116 | } -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-20x20@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-20x20@2x-1.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-29x29@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-29x29@2x-1.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-40x40@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-40x40@2x-1.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-iTunes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Football.appiconset/Icon-App-iTunes.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "40x40", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-40x40@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@3x.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "60x60", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-60x60@2x.png", 43 | "scale" : "2x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@3x.png", 49 | "scale" : "3x" 50 | }, 51 | { 52 | "size" : "20x20", 53 | "idiom" : "ipad", 54 | "filename" : "Icon-App-20x20@1x.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@2x-1.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "29x29", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-29x29@1x.png", 67 | "scale" : "1x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@2x-1.png", 73 | "scale" : "2x" 74 | }, 75 | { 76 | "size" : "40x40", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-40x40@1x.png", 79 | "scale" : "1x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@2x-1.png", 85 | "scale" : "2x" 86 | }, 87 | { 88 | "size" : "76x76", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-76x76@1x.png", 91 | "scale" : "1x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@2x.png", 97 | "scale" : "2x" 98 | }, 99 | { 100 | "size" : "83.5x83.5", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-83.5x83.5@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "1024x1024", 107 | "idiom" : "ios-marketing", 108 | "filename" : "Icon-App-iTunes.png", 109 | "scale" : "1x" 110 | } 111 | ], 112 | "info" : { 113 | "version" : 1, 114 | "author" : "xcode" 115 | } 116 | } -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-20x20@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-20x20@2x-1.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-29x29@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-29x29@2x-1.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-40x40@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-40x40@2x-1.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-iTunes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Panda.appiconset/Icon-App-iTunes.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "40x40", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-40x40@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@3x.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "60x60", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-60x60@2x.png", 43 | "scale" : "2x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@3x.png", 49 | "scale" : "3x" 50 | }, 51 | { 52 | "size" : "20x20", 53 | "idiom" : "ipad", 54 | "filename" : "Icon-App-20x20@1x.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@2x-1.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "29x29", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-29x29@1x.png", 67 | "scale" : "1x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@2x-1.png", 73 | "scale" : "2x" 74 | }, 75 | { 76 | "size" : "40x40", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-40x40@1x.png", 79 | "scale" : "1x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@2x-1.png", 85 | "scale" : "2x" 86 | }, 87 | { 88 | "size" : "76x76", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-76x76@1x.png", 91 | "scale" : "1x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@2x.png", 97 | "scale" : "2x" 98 | }, 99 | { 100 | "size" : "83.5x83.5", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-83.5x83.5@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "1024x1024", 107 | "idiom" : "ios-marketing", 108 | "filename" : "Icon-App-iTunes.png", 109 | "scale" : "1x" 110 | } 111 | ], 112 | "info" : { 113 | "version" : 1, 114 | "author" : "xcode" 115 | } 116 | } -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-20x20@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-20x20@2x-1.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-29x29@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-29x29@2x-1.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-40x40@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-40x40@2x-1.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-iTunes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/AlternateIcons.xcassets/Rocket.appiconset/Icon-App-iTunes.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | @UIApplicationMain 4 | class AppDelegate: UIResponder, UIApplicationDelegate { 5 | 6 | var window: UIWindow? 7 | 8 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 9 | return true 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "40x40", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-40x40@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@3x.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "60x60", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-60x60@2x.png", 43 | "scale" : "2x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@3x.png", 49 | "scale" : "3x" 50 | }, 51 | { 52 | "size" : "20x20", 53 | "idiom" : "ipad", 54 | "filename" : "Icon-App-20x20@1x.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@2x-1.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "29x29", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-29x29@1x.png", 67 | "scale" : "1x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@2x-1.png", 73 | "scale" : "2x" 74 | }, 75 | { 76 | "size" : "40x40", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-40x40@1x.png", 79 | "scale" : "1x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@2x-1.png", 85 | "scale" : "2x" 86 | }, 87 | { 88 | "size" : "76x76", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-76x76@1x.png", 91 | "scale" : "1x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@2x.png", 97 | "scale" : "2x" 98 | }, 99 | { 100 | "size" : "83.5x83.5", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-83.5x83.5@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "1024x1024", 107 | "idiom" : "ios-marketing", 108 | "filename" : "Icon-App-iTunes.png", 109 | "scale" : "1x" 110 | } 111 | ], 112 | "info" : { 113 | "version" : 1, 114 | "author" : "xcode" 115 | } 116 | } -------------------------------------------------------------------------------- /Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x-1.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x-1.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x-1.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-iTunes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/Demo/AlternateIcons/Assets.xcassets/AppIcon.appiconset/Icon-App-iTunes.png -------------------------------------------------------------------------------- /Demo/AlternateIcons/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 41 | 46 | 47 | 48 | 49 | 50 | 51 | 56 | 61 | 62 | 63 | 64 | 65 | 66 | 71 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /Demo/AlternateIcons/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 47 | 58 | 59 | 60 | 61 | 62 | 63 | 74 | 85 | 86 | 87 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /Demo/AlternateIcons/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Demo/AlternateIcons/ViewController.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | class ViewController: UIViewController { 4 | 5 | @IBAction func didTapEmojiButton(sender: UIButton) { 6 | 7 | guard let rawIconName = sender.value(forKey: "iconName") as? String else { 8 | reportError(message: "Button not set up correctly.") 9 | return 10 | } 11 | 12 | let iconName = rawIconName == "AppIcon" ? nil : rawIconName 13 | 14 | UIApplication.shared.setAlternateIconName(iconName) { error in 15 | 16 | guard let error = error else { 17 | return 18 | } 19 | 20 | self.reportError(message: (error as NSError).localizedDescription) 21 | 22 | } 23 | 24 | } 25 | 26 | func reportError(message: String) { 27 | 28 | let alert = UIAlertController(title: "Cannot Change Icon", 29 | message: message, 30 | preferredStyle: .alert) 31 | 32 | let done = UIAlertAction(title: "Done", style: .default, handler: nil) 33 | 34 | alert.addAction(done) 35 | 36 | present(alert, animated: true) 37 | 38 | } 39 | 40 | } 41 | 42 | @objc class IconButton: UIButton { 43 | @objc dynamic var iconName: String? = nil 44 | } 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Alexis Aubry Radanovic 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .DEFAULT_GOAL := build 2 | INSTALL_PATH = /usr/local/bin/embed-alternate-icons 3 | 4 | build: 5 | swift package clean 6 | swift package update 7 | swift build -c release 8 | 9 | install: 10 | cp -f .build/release/AlternateIcons $(INSTALL_PATH) 11 | 12 | release: 13 | mkdir $(RELEASE_NAME) 14 | cp -f .build/release/AlternateIcons $(RELEASE_NAME)/embed-alternate-icons 15 | cp -f install.sh $(RELEASE_NAME)/install.sh 16 | chmod +x $(RELEASE_NAME)/install.sh 17 | tar -cvzf $(RELEASE_NAME).tar.gz $(RELEASE_NAME) 18 | 19 | uninstall: 20 | rm -f $(INSTALL_PATH) 21 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:4.0 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "AlternateIcons", 7 | dependencies: [ 8 | .package(url: "https://github.com/JohnSundell/Files.git", from: "2.0.0") 9 | ], 10 | targets: [ 11 | .target(name: "AltKit", dependencies: ["Files"]), 12 | .target(name: "AlternateIcons", dependencies: ["AltKit"]), 13 | .testTarget(name: "AltKitTests", dependencies: ["AltKit"]) 14 | ] 15 | ) 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AlternateIcons 2 | 3 | [![Build Status](https://travis-ci.org/alexaubry/alternate-icons.svg?branch=master)](https://travis-ci.org/alexaubry/alternate-icons) 4 | [![Requires macOS 10.10+](https://img.shields.io/badge/macOS-10.10+-9D88A2.svg)]() 5 | [![Requires Swift 4.0](https://img.shields.io/badge/Swift-4.0-ee4f37.svg)]() 6 | [![Requires Xcode 9](https://img.shields.io/badge/Xcode-9%20and%20later-blue.svg)]() 7 | 8 | AlternateIcons is a Swift script that automates adding alternate app icons to your iOS app. Group your alternate icons inside an asset catalog, add a build phase and let the script set up your app. No more manual maintenance required! 9 | 10 | ## Installation 11 | 12 | ### From a Pre-built Archive 13 | 14 | You can download a pre-compiled binary for the version you want to install in the [Releases](https://github.com/alexaubry/alternate-icons/releases) section of this repository. 15 | 16 | Once the archive is expanded, run the `install.sh` script to install the script on your system. 17 | 18 | ### From Source 19 | 20 | You can build and install AlternateIcons from source using **Make**: 21 | 22 | ~~~bash 23 | git clone https://github.com/alexaubry/alternate-icons.git 24 | cd alternate-icons 25 | make 26 | make install 27 | ~~~ 28 | 29 | ## Setting up your app 30 | 31 | To set up AlternateIcons as an Xcode build phase, do the following: 32 | 33 | 1. Add your main icon to your main asset catalog. 34 | 35 | 2. Create a new Xcode asset catalog to store your icons, and **do not add it to your target**. 36 | 37 | > **NOTE** In this example, we'll name the catalog "AlternateIcons". 38 | 39 | 3. Add your alternate app icons to this asset catalog, using the '*New iOS App Icon*' template. 40 | 41 | 4. In the Build Phases section of your project target, add a new Run Script phase. The script should be: 42 | 43 | ~~~ 44 | embed-alternate-icons 45 | ~~~ 46 | 47 | You now need to specify the path to the Asset Catalog you've created at step *2* under "Input Files", for example: 48 | 49 | ~~~ 50 | $(SRCROOT)/AlternateIcons.xcassets 51 | ~~~ 52 | 53 | **NOTE**: This Run Script phase needs to be the last build phase in your build. 54 | 55 | 5. Build your app. 56 | 57 | *Et voilà*! All the icons have automatically been embedded into your app and are ready for use! 58 | 59 | ### Changing the icon 60 | 61 | You can now change the icon from your code using: 62 | 63 | ~~~swift 64 | UIApplication.shared.setAlternateIconName(iconName) { error in 65 | // handle the result 66 | } 67 | ~~~ 68 | 69 | Where `iconName` is the name of an icon set in your alternate icons asset catalog or `nil` if you want to return to the default icon. 70 | 71 | > 📚 Read the documentation on [developer.apple.com](https://developer.apple.com/documentation/uikit/uiapplication/2806818-setalternateiconname) 72 | 73 | ## Demo 74 | 75 | A demo project is included in the `Demo/` folder, to help you set up your app. 76 | 77 | Make sure to [install](#installation) AlternateIcons before you build it. 78 | 79 | ## How it works 80 | 81 | Every time you build your app, the script will perform the following steps: 82 | 83 | 1. Get the build products location from environment variables passed by Xcode 84 | 2. Parse the Asset Catalog to build a list of icons to embed 85 | 3. Copy the alternate icon files in the app bundle 86 | 4. Update the `CFBundleIcon` and `CFBundleIcon~ipad` sections of the Info.plist with the list of alternate icon file names 87 | 88 | ## Authors 89 | 90 | Alexis Aubry, me@alexaubry.fr <[@_alexaubry](https://twitter.com/_alexaubry)> 91 | 92 | ## Acknowledgements 93 | 94 | AlternateIcons uses these open source libraries: 95 | 96 | - [Files](https://github.com/JohnSundell/Files) by **@JohnSundell** -------------------------------------------------------------------------------- /Sources/AltKit/AppIconSet.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Files 3 | 4 | /// The list of files contained in an app icon set. 5 | typealias AppIconFiles = [(name: String, source: File, destination: String)] 6 | 7 | /// 8 | /// A set of source images for the different sizes and resolutions of your iOS app icon. 9 | /// 10 | 11 | class AppIconSet { 12 | 13 | /// 14 | /// An image from the set. 15 | /// 16 | 17 | struct Image: Decodable { 18 | 19 | /// The name of the `.png` file. 20 | let filename: String? 21 | 22 | /// The idiom of the icon. 23 | let idiom: String 24 | 25 | /// One of the sizes that matches the idiom for the icon. 26 | let size: String 27 | 28 | /// The scale of the icon. 29 | let scale: String 30 | 31 | } 32 | 33 | 34 | // MARK: - Properties 35 | 36 | /// The folder of the icon set. 37 | let folder: Folder 38 | 39 | /// The variants of the icon. 40 | let images: [Image] 41 | 42 | /// The name of the icon set. 43 | var name: String { 44 | return folder.nameExcludingExtension 45 | } 46 | 47 | 48 | // MARK: - Lifecycle 49 | 50 | private struct RawAppIconSet: Decodable { 51 | let images: [AppIconSet.Image] 52 | } 53 | 54 | /// 55 | /// Creates an app icon set reference. 56 | /// 57 | /// - parameter folder: The folder containing the icon set. 58 | /// 59 | 60 | init(folder: Folder) throws { 61 | 62 | let contentsJSON = try folder.file(named: "Contents.json") 63 | let contentsData = try contentsJSON.read() 64 | let rawIconSet = try JSONDecoder().decode(RawAppIconSet.self, from: contentsData) 65 | 66 | self.images = rawIconSet.images.filter { $0.filename != nil } 67 | self.folder = folder 68 | 69 | } 70 | 71 | 72 | // MARK: - Files 73 | 74 | /// 75 | /// Enumerates the image files. 76 | /// 77 | /// - parameter filter: Whether the image should be included. 78 | /// 79 | /// Returns the source file and the name of the destination file in the app bundle. 80 | /// 81 | 82 | func enumerateImageFiles(unique: Bool, filter: (Image) -> Bool) -> AppIconFiles { 83 | 84 | var files = AppIconFiles() 85 | 86 | for image in images.filter(filter) { 87 | 88 | let fileName = name + image.size 89 | 90 | if unique && files.contains(where: { $0.name == fileName }) { 91 | continue 92 | } 93 | 94 | guard let source = try? folder.file(named: image.filename!) else { 95 | continue 96 | } 97 | 98 | let designationIdiom = image.idiom == "ipad" ? "~ipad" : "" 99 | let destinationScale = image.scale == "1x" ? "" : "@" + image.scale 100 | 101 | let destination = fileName + destinationScale + designationIdiom + ".png" 102 | 103 | let item = (fileName, source, destination) 104 | files.append(item) 105 | 106 | } 107 | 108 | return files 109 | 110 | } 111 | 112 | } 113 | 114 | // MARK: - AppIconSet.Image + Hashable 115 | 116 | extension AppIconSet.Image: Equatable { 117 | 118 | static func == (lhs: AppIconSet.Image, rhs: AppIconSet.Image) -> Bool { 119 | return lhs.filename == rhs.filename && lhs.idiom == rhs.idiom && lhs.size == rhs.size && lhs.scale == rhs.scale 120 | } 121 | 122 | } 123 | 124 | 125 | // MARK: - AppIconSet + Hashable 126 | 127 | extension AppIconSet: Hashable { 128 | 129 | var hashValue: Int { 130 | return ObjectIdentifier(self).hashValue 131 | } 132 | 133 | static func == (lhs: AppIconSet, rhs: AppIconSet) -> Bool { 134 | return lhs === rhs 135 | } 136 | 137 | } 138 | -------------------------------------------------------------------------------- /Sources/AltKit/AssetCatalog.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Files 3 | 4 | /// 5 | /// Represents an Xcode asset catalog. 6 | /// 7 | 8 | struct AssetCatalog: Equatable { 9 | 10 | /// The catalog folder. 11 | var folder: Folder 12 | 13 | /// 14 | /// Lists the App Icon Sets in the catalog. 15 | /// 16 | 17 | func listAppIconSets() throws -> Set { 18 | 19 | let appIconSets = try folder.subfolders 20 | .filter { $0.containsFile(named: "Contents.json") && $0.extension == "appiconset" } 21 | .map(AppIconSet.init) 22 | 23 | return Set(appIconSets) 24 | 25 | } 26 | 27 | static func == (lhs: AssetCatalog, rhs: AssetCatalog) -> Bool { 28 | return lhs.folder == rhs.folder 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /Sources/AltKit/BundleIcon.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// 4 | /// An icon from the app bundle. 5 | /// 6 | 7 | struct BundleIcon: Hashable { 8 | 9 | let name: String 10 | let files: [String] 11 | 12 | var hashValue: Int { 13 | return name.hashValue 14 | } 15 | 16 | static func == (lhs: BundleIcon, rhs: BundleIcon) -> Bool { 17 | return lhs.name == rhs.name 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /Sources/AltKit/Error.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// 4 | /// The list of known errors. 5 | /// 6 | 7 | enum AltError: String, LocalizedError { 8 | 9 | /// The Info.plist file could not be read. 10 | case noInfoPlist = "The Info.plist file could not be read." 11 | 12 | /// The Info.plist file is not a valid XML Property List. 13 | case invalidInfoPlist = "The Info.plist file is not a valid XML Property List." 14 | 15 | /// The asset catalog could not be read. 16 | case noAssetCatalog = "The asset catalog could not be read." 17 | 18 | /// The app bundle could not be found. 19 | case noAppBundle = "The app bundle could not be found." 20 | 21 | /// No app icon set named 'AppIcon' was found. 22 | case noPrimaryIconSet = "No app icon set named 'AppIcon' was found." 23 | 24 | var errorDescription: String? { 25 | return rawValue 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /Sources/AltKit/InfoPlist.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Files 3 | 4 | /// 5 | /// The representation of the information Property List of an app (`Info.plist`). 6 | /// 7 | 8 | class InfoPlist { 9 | 10 | /// The handle to the underlying `Info.plist` file. 11 | var file: File 12 | 13 | /// The properties in the `Info.plist` file. 14 | var infoDictionary: [AnyHashable: Any] 15 | 16 | 17 | // MARK: - Lifecycle 18 | 19 | /// 20 | /// Creates an InfoPlist object from an `Info.plist` file. 21 | /// 22 | /// - parameter file: The `Info.plist` file to parse. 23 | /// 24 | 25 | init(file: File) throws { 26 | 27 | let fileData = try file.read() 28 | let infoObject = try PropertyListSerialization.propertyList(from: fileData, options: [], format: nil) 29 | 30 | guard let infoDictionary = infoObject as? [AnyHashable: Any] else { 31 | throw AltError.invalidInfoPlist 32 | } 33 | 34 | self.file = file 35 | self.infoDictionary = infoDictionary 36 | 37 | } 38 | 39 | /// 40 | /// Updates the Info.plist file with a new set of icons. 41 | /// 42 | /// - parameter alternateIcons: The list of alternate app icons to use. 43 | /// 44 | 45 | func update(alternateIcons: Set) { 46 | 47 | let alternateIconsFiles = getAlternateIconFiles(in: alternateIcons) { $0.idiom == "iphone" } 48 | let alternateiPadIconsFiles = getAlternateIconFiles(in: alternateIcons) { $0.idiom == "ipad" } 49 | 50 | var icons = infoDictionary[InfoPlist.iconsKey] as? [AnyHashable: Any] ?? [:] 51 | var ipadIcons = infoDictionary[InfoPlist.ipadIconsKey] as? [AnyHashable: Any] ?? [:] 52 | 53 | icons[InfoPlist.alternateIconsKey] = alternateIconsFiles 54 | ipadIcons[InfoPlist.alternateIconsKey] = alternateiPadIconsFiles 55 | 56 | infoDictionary[InfoPlist.iconsKey] = icons 57 | infoDictionary[InfoPlist.ipadIconsKey] = ipadIcons 58 | 59 | } 60 | 61 | /// 62 | /// Get the alternate icon files dictionary for the given subset of icons. 63 | /// 64 | /// - parameter alternateIc 65 | /// 66 | 67 | func getAlternateIconFiles(in alternateIcons: Set, filter: (AppIconSet.Image) -> Bool) -> [AnyHashable: Any] { 68 | 69 | return alternateIcons.reduce([AnyHashable: Any]()) { 70 | result, next in 71 | 72 | let files = next.enumerateImageFiles(unique: true, filter: filter).map { $0.name } 73 | 74 | var resultCopy = result 75 | resultCopy[next.name] = [ 76 | InfoPlist.iconFilesKey: files 77 | ] 78 | 79 | return resultCopy 80 | 81 | } 82 | 83 | } 84 | 85 | /// 86 | /// Writes any changes made to the info dictionary to the original `Info.plist` file. 87 | /// 88 | /// - note: This method is de-coupled from `update(primaryIcon:,alternateIcons:)` for 89 | /// testing purposes. 90 | /// 91 | 92 | func commitChanges() throws { 93 | let plistData = try PropertyListSerialization.data(fromPropertyList: infoDictionary, format: .xml, options: 0) 94 | try file.write(data: plistData) 95 | } 96 | 97 | } 98 | 99 | 100 | // MARK: - Keys 101 | 102 | extension InfoPlist { 103 | 104 | /// The app icons dictionary. 105 | static var iconsKey = "CFBundleIcons" 106 | 107 | /// The iPad app icons dictionary. 108 | static var ipadIconsKey = "CFBundleIcons~ipad" 109 | 110 | /// The alternate icon dictionary. 111 | static var alternateIconsKey = "CFBundleAlternateIcons" 112 | 113 | /// The icon file names. 114 | static var iconFilesKey = "CFBundleIconFiles" 115 | 116 | } 117 | 118 | 119 | // MARK: - InfoPlist + Equatable 120 | 121 | extension InfoPlist: Equatable { 122 | 123 | static func == (lhs: InfoPlist, rhs: InfoPlist) -> Bool { 124 | return lhs.file == rhs.file 125 | } 126 | 127 | } 128 | -------------------------------------------------------------------------------- /Sources/AltKit/Script.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import Files 3 | 4 | /// 5 | /// The main entry point of the script. 6 | /// 7 | 8 | public enum Script { 9 | 10 | /// 11 | /// The arguments required to execute the program. 12 | /// 13 | 14 | public struct Arguments { 15 | 16 | /// The information plist file. 17 | let infoPlist: InfoPlist 18 | 19 | /// The asset catalog folder containing the alternate icons. 20 | let assetCatalog: AssetCatalog 21 | 22 | /// The app bundle. 23 | let appBundle: Folder 24 | 25 | } 26 | 27 | 28 | // MARK: - Execution 29 | 30 | /// 31 | /// Reads the arguments from the current context. 32 | /// 33 | /// - note: The basePath parameter must only be used for unit testing. 34 | /// 35 | 36 | public static func readArguments(resolvingAgainst basePath: String = "") throws -> Arguments { 37 | 38 | // 1) Asset Catalog 39 | 40 | guard let scriptInputFiles = Xcode.scriptInputFiles else { 41 | throw AltError.noAssetCatalog 42 | } 43 | 44 | guard scriptInputFiles.count > 0 else { 45 | throw AltError.noAssetCatalog 46 | } 47 | 48 | let assetCatalogPath = scriptInputFiles[0] 49 | let assetCatalogFolder = try Folder(path: basePath + assetCatalogPath) 50 | 51 | // 2) App Bundle 52 | 53 | let buildPath = Xcode.buildProductsDir ?? basePath 54 | 55 | guard let contentsDir = Xcode.contentsFolderPath else { 56 | throw AltError.noAppBundle 57 | } 58 | 59 | let appBundlePath = buildPath.appending(pathComponent: contentsDir) 60 | 61 | // 3) Info Plist 62 | 63 | let infoPlistPath = appBundlePath.appending(pathComponent: "Info.plist") 64 | let infoPlistFile = try File(path: infoPlistPath) 65 | 66 | let infoPlist = try InfoPlist(file: infoPlistFile) 67 | let assetCatalog = AssetCatalog(folder: assetCatalogFolder) 68 | let appBundle = try Folder(path: appBundlePath) 69 | 70 | return Arguments(infoPlist: infoPlist, 71 | assetCatalog: assetCatalog, 72 | appBundle: appBundle) 73 | 74 | } 75 | 76 | /// 77 | /// Executes the script with the given arguments. 78 | /// 79 | 80 | public static func run(with arguments: Arguments) throws { 81 | 82 | // 1) Read Asset Catalog 83 | 84 | step("Reading \(arguments.assetCatalog.folder.name) asset catalog") 85 | let alternateIconSets = try arguments.assetCatalog.listAppIconSets() 86 | 87 | // 2) Copy all icons into app bundle 88 | 89 | let iconImagesNames = alternateIconSets.map { $0.enumerateImageFiles(unique: false) { $0.idiom == "iphone" || $0.idiom == "ipad" } } 90 | let iconImages = merge(iconImagesNames) 91 | 92 | step("Copying \(iconImages.count) icons into place") 93 | 94 | for image in iconImages { 95 | 96 | let destinationPath = arguments.appBundle.path.appending(pathComponent: image.destination) 97 | 98 | if FileManager.default.fileExists(atPath: destinationPath) { 99 | try FileManager.default.removeItem(atPath: destinationPath) 100 | } 101 | 102 | try FileManager.default.copyItem(atPath: image.source.path, toPath: destinationPath) 103 | 104 | } 105 | 106 | // 3) Update Info.plist 107 | 108 | step("Updating Info.plist with new icons") 109 | 110 | arguments.infoPlist.update(alternateIcons: alternateIconSets) 111 | try arguments.infoPlist.commitChanges() 112 | 113 | } 114 | 115 | /// 116 | /// Shows an error message and exits the script. 117 | /// 118 | 119 | public static func fail(reason: String) -> Never { 120 | 121 | let message = "💥 \(reason)\n".utf8 122 | let messageData = Data(message) 123 | 124 | FileHandle.standardError.write(messageData) 125 | exit(1) 126 | 127 | } 128 | 129 | /// 130 | /// Prints a step of the script. 131 | /// 132 | 133 | public static func step(_ description: String, emoji: String = "👉") { 134 | 135 | let message = "\(emoji) \(description)\n".utf8 136 | let messageData = Data(message) 137 | 138 | FileHandle.standardOutput.write(messageData) 139 | 140 | } 141 | 142 | /// 143 | /// Marks the script as completed and exits with code 0. 144 | /// 145 | 146 | public static func done() { 147 | step("Done! All icons were embedded successfully.", emoji: "✅") 148 | exit(0) 149 | } 150 | 151 | } 152 | 153 | 154 | // MARK: - Utilities 155 | 156 | extension String { 157 | 158 | /// 159 | /// Appends a path component to the string. 160 | /// 161 | 162 | func appending(pathComponent: String) -> String { 163 | 164 | guard !isEmpty else { 165 | return self 166 | } 167 | 168 | let pathJoiner = hasSuffix("/") ? "" : "/" 169 | return self + pathJoiner + pathComponent 170 | 171 | } 172 | 173 | /// The name of the item (excluding any extension). 174 | var excludingExtension: String { 175 | guard let `extension` = `extension` else { 176 | return self 177 | } 178 | 179 | let startIndex = index(endIndex, offsetBy: -`extension`.characters.count - 1) 180 | return replacingCharacters(in: startIndex.. 1 else { 188 | return nil 189 | } 190 | 191 | return components.last 192 | } 193 | 194 | } 195 | 196 | /// 197 | /// Combines an array of arrays into a single array. 198 | /// 199 | 200 | func merge(_ arraysToMerge: @autoclosure () -> [[Base]]) -> [Base] { 201 | 202 | let arrays = arraysToMerge() 203 | 204 | return arrays.reduce([Base]()) { 205 | result, next in 206 | var mutableResults = result 207 | mutableResults.append(contentsOf: next) 208 | return mutableResults 209 | } 210 | 211 | } 212 | -------------------------------------------------------------------------------- /Sources/AltKit/Xcode.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | /// 4 | /// A set of environment variables exported by Xcode during build phases. 5 | /// 6 | 7 | enum Xcode { 8 | 9 | /// The path to the build products directory. 10 | static var buildProductsDir: String? { 11 | return get(variable: "BUILT_PRODUCTS_DIR") 12 | } 13 | 14 | /// The path to the contents folder. 15 | static var contentsFolderPath: String? { 16 | return get(variable: "CONTENTS_FOLDER_PATH") 17 | } 18 | 19 | /// The input files of the script. 20 | static var scriptInputFiles: [String]? { 21 | 22 | guard let count = get(variable: "SCRIPT_INPUT_FILE_COUNT").flatMap({ Int($0) }) else { 23 | return nil 24 | } 25 | 26 | var inputFiles = [String]() 27 | 28 | for index in 0 ..< count { 29 | 30 | guard let path = get(variable: "SCRIPT_INPUT_FILE_\(index)") else { 31 | return nil 32 | } 33 | 34 | inputFiles.append(path) 35 | 36 | } 37 | 38 | return inputFiles 39 | 40 | } 41 | 42 | 43 | // MARK: - Utilities 44 | 45 | /// 46 | /// Returns the value of the environment variable. 47 | /// 48 | 49 | static func get(variable: String) -> String? { 50 | 51 | guard let cVariable = getenv(variable) else { 52 | return nil 53 | } 54 | 55 | return String(cString: cVariable) 56 | 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /Sources/AlternateIcons/main.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | import AltKit 3 | 4 | do { 5 | Script.step("Parsing build context") 6 | let arguments = try Script.readArguments() 7 | try Script.run(with: arguments) 8 | Script.done() 9 | 10 | } catch let error as LocalizedError { 11 | Script.fail(reason: error.errorDescription ?? "Unknown error") 12 | 13 | } catch { 14 | Script.fail(reason: error.localizedDescription) 15 | } 16 | 17 | -------------------------------------------------------------------------------- /TestFixtures/AlternateInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | fr_FR 7 | CFBundleDisplayName 8 | AlternateIcons 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0.0 21 | CFBundleVersion 22 | 32 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UIStatusBarStyle 32 | UIStatusBarStyleLightContent 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationPortraitUpsideDown 37 | 38 | UISupportedInterfaceOrientations~ipad 39 | 40 | UIInterfaceOrientationPortrait 41 | UIInterfaceOrientationPortraitUpsideDown 42 | UIInterfaceOrientationLandscapeLeft 43 | UIInterfaceOrientationLandscapeRight 44 | 45 | CFBundleIcons 46 | 47 | CFBundleAlternateIcons 48 | 49 | barca 50 | 51 | CFBundleIconFiles 52 | 53 | ic_barca 54 | 55 | UIPrerenderedIcon 56 | 57 | 58 | ams 59 | 60 | CFBundleIconFiles 61 | 62 | ic_ams 63 | 64 | UIPrerenderedIcon 65 | 66 | 67 | paris 68 | 69 | CFBundleIconFiles 70 | 71 | ic_paris 72 | 73 | UIPrerenderedIcon 74 | 75 | 76 | 77 | 78 | CFBundleIcons~ipad 79 | 80 | CFBundleAlternateIcons 81 | 82 | barca 83 | 84 | CFBundleIconFiles 85 | 86 | ic_barca 87 | 88 | UIPrerenderedIcon 89 | 90 | 91 | ams 92 | 93 | CFBundleIconFiles 94 | 95 | ic_ams 96 | 97 | UIPrerenderedIcon 98 | 99 | 100 | paris 101 | 102 | CFBundleIconFiles 103 | 104 | ic_paris 105 | 106 | UIPrerenderedIcon 107 | 108 | 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /TestFixtures/AppBundle/AppIconOld@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/AppBundle/AppIconOld@2x.png -------------------------------------------------------------------------------- /TestFixtures/AppBundle/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleIcons 6 | 7 | CFBundleAlternateIcons 8 | 9 | old 10 | 11 | CFBundleIconFiles 12 | 13 | AppIconOld@2x 14 | 15 | UIPrerenderedIcon 16 | 17 | 18 | 19 | 20 | CFBundleDevelopmentRegion 21 | fr_FR 22 | CFBundleDisplayName 23 | AlternateIcons 24 | CFBundleExecutable 25 | $(EXECUTABLE_NAME) 26 | CFBundleIdentifier 27 | $(PRODUCT_BUNDLE_IDENTIFIER) 28 | CFBundleInfoDictionaryVersion 29 | 6.0 30 | CFBundleName 31 | $(PRODUCT_NAME) 32 | CFBundlePackageType 33 | APPL 34 | CFBundleShortVersionString 35 | 1.0.0 36 | CFBundleVersion 37 | 32 38 | LSRequiresIPhoneOS 39 | 40 | UILaunchStoryboardName 41 | LaunchScreen 42 | UIRequiredDeviceCapabilities 43 | 44 | armv7 45 | 46 | UIStatusBarStyle 47 | UIStatusBarStyleLightContent 48 | UISupportedInterfaceOrientations 49 | 50 | UIInterfaceOrientationPortrait 51 | UIInterfaceOrientationPortraitUpsideDown 52 | 53 | UISupportedInterfaceOrientations~ipad 54 | 55 | UIInterfaceOrientationPortrait 56 | UIInterfaceOrientationPortraitUpsideDown 57 | UIInterfaceOrientationLandscapeLeft 58 | UIInterfaceOrientationLandscapeRight 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-Small.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-Small@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-Small@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-Small-40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-Small-40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "57x57", 47 | "idiom" : "iphone", 48 | "filename" : "Icon.png", 49 | "scale" : "1x" 50 | }, 51 | { 52 | "size" : "57x57", 53 | "idiom" : "iphone", 54 | "filename" : "Icon@2x.png", 55 | "scale" : "2x" 56 | }, 57 | { 58 | "size" : "60x60", 59 | "idiom" : "iphone", 60 | "filename" : "Icon-60@2x.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "60x60", 65 | "idiom" : "iphone", 66 | "filename" : "Icon-60@3x.png", 67 | "scale" : "3x" 68 | }, 69 | { 70 | "size" : "20x20", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-20.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "20x20", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-20@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "29x29", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-Small-1.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "29x29", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-Small@2x-1.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "40x40", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-Small-40.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "40x40", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-Small-40@2x-1.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "50x50", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-Small-50.png", 109 | "scale" : "1x" 110 | }, 111 | { 112 | "size" : "50x50", 113 | "idiom" : "ipad", 114 | "filename" : "Icon-Small-50@2x.png", 115 | "scale" : "2x" 116 | }, 117 | { 118 | "size" : "72x72", 119 | "idiom" : "ipad", 120 | "filename" : "Icon-72.png", 121 | "scale" : "1x" 122 | }, 123 | { 124 | "size" : "72x72", 125 | "idiom" : "ipad", 126 | "filename" : "Icon-72@2x.png", 127 | "scale" : "2x" 128 | }, 129 | { 130 | "size" : "76x76", 131 | "idiom" : "ipad", 132 | "filename" : "Icon-76.png", 133 | "scale" : "1x" 134 | }, 135 | { 136 | "size" : "76x76", 137 | "idiom" : "ipad", 138 | "filename" : "Icon-76@2x.png", 139 | "scale" : "2x" 140 | }, 141 | { 142 | "size" : "83.5x83.5", 143 | "idiom" : "ipad", 144 | "filename" : "Icon-83.5@2x.png", 145 | "scale" : "2x" 146 | }, 147 | { 148 | "idiom" : "ios-marketing", 149 | "size" : "1024x1024", 150 | "scale" : "1x" 151 | }, 152 | { 153 | "idiom" : "fake", 154 | "size" : "1024x1024", 155 | "scale" : "1x", 156 | "filename": "fake.png" 157 | } 158 | ], 159 | "info" : { 160 | "version" : 1, 161 | "author" : "xcode" 162 | } 163 | } -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-20.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-20@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-20@3x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-72.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-72@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-76.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-83.5@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-Small-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-Small-1.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-Small-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-Small-40.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-Small-40@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-Small-40@2x-1.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-Small-40@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-Small-40@3x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-Small-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-Small-50.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-Small-50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-Small-50@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-Small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-Small.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-Small@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-Small@2x-1.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-Small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-Small@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-Small@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/AppIcon.appiconset/Icon-Small@3x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/AppIcon.appiconset/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/AppIcon.appiconset/Icon.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/AppIcon.appiconset/Icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/AppIcon.appiconset/Icon@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "filename" : "Default-iOS7@2x.png", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "extent" : "full-screen", 13 | "idiom" : "iphone", 14 | "subtype" : "retina4", 15 | "filename" : "Default-iOS7-568h@2x.png", 16 | "minimum-system-version" : "7.0", 17 | "orientation" : "portrait", 18 | "scale" : "2x" 19 | }, 20 | { 21 | "orientation" : "portrait", 22 | "idiom" : "ipad", 23 | "extent" : "full-screen", 24 | "minimum-system-version" : "7.0", 25 | "filename" : "Default-iOS7-Portrait.png", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "orientation" : "landscape", 30 | "idiom" : "ipad", 31 | "extent" : "full-screen", 32 | "minimum-system-version" : "7.0", 33 | "filename" : "Default-iOS7-Landscape.png", 34 | "scale" : "1x" 35 | }, 36 | { 37 | "orientation" : "portrait", 38 | "idiom" : "ipad", 39 | "extent" : "full-screen", 40 | "minimum-system-version" : "7.0", 41 | "filename" : "Default-iOS7-Portrait@2x.png", 42 | "scale" : "2x" 43 | }, 44 | { 45 | "orientation" : "landscape", 46 | "idiom" : "ipad", 47 | "extent" : "full-screen", 48 | "minimum-system-version" : "7.0", 49 | "filename" : "Default-iOS7-Landscape@2x.png", 50 | "scale" : "2x" 51 | }, 52 | { 53 | "orientation" : "portrait", 54 | "idiom" : "iphone", 55 | "extent" : "full-screen", 56 | "filename" : "Default.png", 57 | "scale" : "1x" 58 | }, 59 | { 60 | "orientation" : "portrait", 61 | "idiom" : "iphone", 62 | "extent" : "full-screen", 63 | "filename" : "Default@2x.png", 64 | "scale" : "2x" 65 | }, 66 | { 67 | "orientation" : "portrait", 68 | "idiom" : "iphone", 69 | "extent" : "full-screen", 70 | "filename" : "Default-568h@2x.png", 71 | "subtype" : "retina4", 72 | "scale" : "2x" 73 | }, 74 | { 75 | "orientation" : "portrait", 76 | "idiom" : "ipad", 77 | "extent" : "to-status-bar", 78 | "filename" : "Default-Portrait.png", 79 | "scale" : "1x" 80 | }, 81 | { 82 | "orientation" : "portrait", 83 | "idiom" : "ipad", 84 | "extent" : "full-screen", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "orientation" : "landscape", 89 | "idiom" : "ipad", 90 | "extent" : "to-status-bar", 91 | "filename" : "Default-Landscape.png", 92 | "scale" : "1x" 93 | }, 94 | { 95 | "orientation" : "landscape", 96 | "idiom" : "ipad", 97 | "extent" : "full-screen", 98 | "scale" : "1x" 99 | }, 100 | { 101 | "orientation" : "portrait", 102 | "idiom" : "ipad", 103 | "extent" : "to-status-bar", 104 | "filename" : "Default-Portrait@2x.png", 105 | "scale" : "2x" 106 | }, 107 | { 108 | "orientation" : "portrait", 109 | "idiom" : "ipad", 110 | "extent" : "full-screen", 111 | "scale" : "2x" 112 | }, 113 | { 114 | "orientation" : "landscape", 115 | "idiom" : "ipad", 116 | "extent" : "to-status-bar", 117 | "filename" : "Default-Landscape@2x.png", 118 | "scale" : "2x" 119 | }, 120 | { 121 | "orientation" : "landscape", 122 | "idiom" : "ipad", 123 | "extent" : "full-screen", 124 | "scale" : "2x" 125 | } 126 | ], 127 | "info" : { 128 | "version" : 1, 129 | "author" : "xcode" 130 | } 131 | } -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/LaunchImage.launchimage/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/LaunchImage.launchimage/Default-568h@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/LaunchImage.launchimage/Default-Landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/LaunchImage.launchimage/Default-Landscape.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/LaunchImage.launchimage/Default-Landscape@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/LaunchImage.launchimage/Default-Landscape@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/LaunchImage.launchimage/Default-Portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/LaunchImage.launchimage/Default-Portrait.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/LaunchImage.launchimage/Default-Portrait@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/LaunchImage.launchimage/Default-Portrait@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/LaunchImage.launchimage/Default-iOS7-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/LaunchImage.launchimage/Default-iOS7-568h@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/LaunchImage.launchimage/Default-iOS7-Landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/LaunchImage.launchimage/Default-iOS7-Landscape.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/LaunchImage.launchimage/Default-iOS7-Landscape@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/LaunchImage.launchimage/Default-iOS7-Landscape@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/LaunchImage.launchimage/Default-iOS7-Portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/LaunchImage.launchimage/Default-iOS7-Portrait.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/LaunchImage.launchimage/Default-iOS7-Portrait@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/LaunchImage.launchimage/Default-iOS7-Portrait@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/LaunchImage.launchimage/Default-iOS7@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/LaunchImage.launchimage/Default-iOS7@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/LaunchImage.launchimage/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/LaunchImage.launchimage/Default.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/LaunchImage.launchimage/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/LaunchImage.launchimage/Default@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Light.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-Small.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-Small@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-Small@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-Small-40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-Small-40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "57x57", 47 | "idiom" : "iphone", 48 | "filename" : "Icon.png", 49 | "scale" : "1x" 50 | }, 51 | { 52 | "size" : "57x57", 53 | "idiom" : "iphone", 54 | "filename" : "Icon@2x.png", 55 | "scale" : "2x" 56 | }, 57 | { 58 | "size" : "60x60", 59 | "idiom" : "iphone", 60 | "filename" : "Icon-60@2x.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "60x60", 65 | "idiom" : "iphone", 66 | "filename" : "Icon-60@3x.png", 67 | "scale" : "3x" 68 | }, 69 | { 70 | "size" : "20x20", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-20.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "20x20", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-20@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "29x29", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-Small-1.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "29x29", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-Small@2x-1.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "40x40", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-Small-40.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "40x40", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-Small-40@2x-1.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "50x50", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-Small-50.png", 109 | "scale" : "1x" 110 | }, 111 | { 112 | "size" : "50x50", 113 | "idiom" : "ipad", 114 | "filename" : "Icon-Small-50@2x.png", 115 | "scale" : "2x" 116 | }, 117 | { 118 | "size" : "72x72", 119 | "idiom" : "ipad", 120 | "filename" : "Icon-72.png", 121 | "scale" : "1x" 122 | }, 123 | { 124 | "size" : "72x72", 125 | "idiom" : "ipad", 126 | "filename" : "Icon-72@2x.png", 127 | "scale" : "2x" 128 | }, 129 | { 130 | "size" : "76x76", 131 | "idiom" : "ipad", 132 | "filename" : "Icon-76.png", 133 | "scale" : "1x" 134 | }, 135 | { 136 | "size" : "76x76", 137 | "idiom" : "ipad", 138 | "filename" : "Icon-76@2x.png", 139 | "scale" : "2x" 140 | }, 141 | { 142 | "size" : "83.5x83.5", 143 | "idiom" : "ipad", 144 | "filename" : "Icon-83.5@2x.png", 145 | "scale" : "2x" 146 | }, 147 | { 148 | "idiom" : "ios-marketing", 149 | "size" : "1024x1024", 150 | "scale" : "1x" 151 | } 152 | ], 153 | "info" : { 154 | "version" : 1, 155 | "author" : "xcode" 156 | } 157 | } -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Light.appiconset/Icon-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Light.appiconset/Icon-20.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Light.appiconset/Icon-20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Light.appiconset/Icon-20@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Light.appiconset/Icon-20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Light.appiconset/Icon-20@3x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Light.appiconset/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Light.appiconset/Icon-60@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Light.appiconset/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Light.appiconset/Icon-60@3x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Light.appiconset/Icon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Light.appiconset/Icon-72.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Light.appiconset/Icon-72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Light.appiconset/Icon-72@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Light.appiconset/Icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Light.appiconset/Icon-76.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Light.appiconset/Icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Light.appiconset/Icon-76@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Light.appiconset/Icon-83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Light.appiconset/Icon-83.5@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Light.appiconset/Icon-Small-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Light.appiconset/Icon-Small-1.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Light.appiconset/Icon-Small-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Light.appiconset/Icon-Small-40.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Light.appiconset/Icon-Small-40@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Light.appiconset/Icon-Small-40@2x-1.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Light.appiconset/Icon-Small-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Light.appiconset/Icon-Small-40@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Light.appiconset/Icon-Small-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Light.appiconset/Icon-Small-40@3x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Light.appiconset/Icon-Small-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Light.appiconset/Icon-Small-50.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Light.appiconset/Icon-Small-50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Light.appiconset/Icon-Small-50@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Light.appiconset/Icon-Small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Light.appiconset/Icon-Small.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Light.appiconset/Icon-Small@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Light.appiconset/Icon-Small@2x-1.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Light.appiconset/Icon-Small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Light.appiconset/Icon-Small@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Light.appiconset/Icon-Small@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Light.appiconset/Icon-Small@3x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Light.appiconset/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Light.appiconset/Icon.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Light.appiconset/Icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Light.appiconset/Icon@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Sombre.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-Small.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-Small@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-Small@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-Small-40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-Small-40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "57x57", 47 | "idiom" : "iphone", 48 | "filename" : "Icon.png", 49 | "scale" : "1x" 50 | }, 51 | { 52 | "size" : "57x57", 53 | "idiom" : "iphone", 54 | "filename" : "Icon@2x.png", 55 | "scale" : "2x" 56 | }, 57 | { 58 | "size" : "60x60", 59 | "idiom" : "iphone", 60 | "filename" : "Icon-60@2x.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "60x60", 65 | "idiom" : "iphone", 66 | "filename" : "Icon-60@3x.png", 67 | "scale" : "3x" 68 | }, 69 | { 70 | "size" : "20x20", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-20.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "20x20", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-20@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "29x29", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-Small-1.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "29x29", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-Small@2x-1.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "40x40", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-Small-40.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "40x40", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-Small-40@2x-1.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "50x50", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-Small-50.png", 109 | "scale" : "1x" 110 | }, 111 | { 112 | "size" : "50x50", 113 | "idiom" : "ipad", 114 | "filename" : "Icon-Small-50@2x.png", 115 | "scale" : "2x" 116 | }, 117 | { 118 | "size" : "72x72", 119 | "idiom" : "ipad", 120 | "filename" : "Icon-72.png", 121 | "scale" : "1x" 122 | }, 123 | { 124 | "size" : "72x72", 125 | "idiom" : "ipad", 126 | "filename" : "Icon-72@2x.png", 127 | "scale" : "2x" 128 | }, 129 | { 130 | "size" : "76x76", 131 | "idiom" : "ipad", 132 | "filename" : "Icon-76.png", 133 | "scale" : "1x" 134 | }, 135 | { 136 | "size" : "76x76", 137 | "idiom" : "ipad", 138 | "filename" : "Icon-76@2x.png", 139 | "scale" : "2x" 140 | }, 141 | { 142 | "size" : "83.5x83.5", 143 | "idiom" : "ipad", 144 | "filename" : "Icon-83.5@2x.png", 145 | "scale" : "2x" 146 | }, 147 | { 148 | "idiom" : "ios-marketing", 149 | "size" : "1024x1024", 150 | "scale" : "1x" 151 | } 152 | ], 153 | "info" : { 154 | "version" : 1, 155 | "author" : "xcode" 156 | } 157 | } -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Sombre.appiconset/Icon-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Sombre.appiconset/Icon-20.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Sombre.appiconset/Icon-20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Sombre.appiconset/Icon-20@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Sombre.appiconset/Icon-20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Sombre.appiconset/Icon-20@3x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Sombre.appiconset/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Sombre.appiconset/Icon-60@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Sombre.appiconset/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Sombre.appiconset/Icon-60@3x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Sombre.appiconset/Icon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Sombre.appiconset/Icon-72.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Sombre.appiconset/Icon-72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Sombre.appiconset/Icon-72@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Sombre.appiconset/Icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Sombre.appiconset/Icon-76.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Sombre.appiconset/Icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Sombre.appiconset/Icon-76@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Sombre.appiconset/Icon-83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Sombre.appiconset/Icon-83.5@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Sombre.appiconset/Icon-Small-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Sombre.appiconset/Icon-Small-1.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Sombre.appiconset/Icon-Small-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Sombre.appiconset/Icon-Small-40.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Sombre.appiconset/Icon-Small-40@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Sombre.appiconset/Icon-Small-40@2x-1.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Sombre.appiconset/Icon-Small-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Sombre.appiconset/Icon-Small-40@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Sombre.appiconset/Icon-Small-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Sombre.appiconset/Icon-Small-40@3x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Sombre.appiconset/Icon-Small-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Sombre.appiconset/Icon-Small-50.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Sombre.appiconset/Icon-Small-50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Sombre.appiconset/Icon-Small-50@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Sombre.appiconset/Icon-Small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Sombre.appiconset/Icon-Small.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Sombre.appiconset/Icon-Small@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Sombre.appiconset/Icon-Small@2x-1.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Sombre.appiconset/Icon-Small@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Sombre.appiconset/Icon-Small@2x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Sombre.appiconset/Icon-Small@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Sombre.appiconset/Icon-Small@3x.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Sombre.appiconset/Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Sombre.appiconset/Icon.png -------------------------------------------------------------------------------- /TestFixtures/Images.xcassets/Sombre.appiconset/Icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexaubry/alternate-icons/e7930e9f0a0354942ac5a46f2e51905e2357873c/TestFixtures/Images.xcassets/Sombre.appiconset/Icon@2x.png -------------------------------------------------------------------------------- /Tests/AltKitTests/AssetCatalogTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import Foundation 3 | import Files 4 | @testable import AltKit 5 | 6 | /// 7 | /// Tests the Asset Catalog parser. 8 | /// 9 | 10 | class AssetCatalogTests: FailableTestCase { 11 | 12 | /// The asset catalog. 13 | var catalog: AssetCatalog! 14 | 15 | 16 | // MARK: - Lifecycle 17 | 18 | override func setUp() { 19 | 20 | let bundle = Bundle(for: InfoPlistTests.self) 21 | let catalogPath = bundle.bundlePath + "/Contents/Resources/TestFixtures/Images.xcassets" 22 | 23 | guard let catalogFolder = try? Folder(path: catalogPath) else { 24 | XCTFail("Could not open the Images.xcassets folder.") 25 | return 26 | } 27 | 28 | catalog = AssetCatalog(folder: catalogFolder) 29 | 30 | } 31 | 32 | override func tearDown() { 33 | catalog = nil 34 | } 35 | 36 | 37 | // MARK: - Tests 38 | 39 | /// 40 | /// Tests that the parser returns the correct list of app icon sets. 41 | /// 42 | 43 | func testListIconSets() throws { 44 | 45 | let iconSets = try catalog.listAppIconSets() 46 | 47 | let expectedNames = ["AppIcon", "Light", "Sombre"] 48 | let iconSetNames = iconSets.map { $0.name }.sorted() 49 | 50 | XCTAssertEqual(iconSetNames, expectedNames) 51 | 52 | } 53 | 54 | /// 55 | /// Tests that all the images are read correctly. 56 | /// 57 | 58 | func testReadImages() throws { 59 | 60 | let iconSets = try catalog.listAppIconSets() 61 | 62 | for set in iconSets { 63 | XCTAssertTrue(set.images.count > 0) 64 | } 65 | 66 | } 67 | 68 | /// 69 | /// Tests the attribution of names. 70 | /// 71 | 72 | func testNames() throws { 73 | 74 | let iconSets = try catalog.listAppIconSets() 75 | 76 | guard let appIconSet = iconSets.first(where: { $0.name == "AppIcon" }) else { 77 | XCTFail("No AppIcon set") 78 | return 79 | } 80 | 81 | let expectedNamesSet: Set = [ 82 | "AppIcon20x20", 83 | "AppIcon29x29", 84 | "AppIcon40x40", 85 | "AppIcon57x57", 86 | "AppIcon60x60", 87 | "AppIcon50x50", 88 | "AppIcon72x72", 89 | "AppIcon76x76", 90 | "AppIcon83.5x83.5" 91 | ] 92 | 93 | let names = appIconSet.enumerateImageFiles(unique: true, filter: { _ in return true }).map { $0.name } 94 | let namesSet = Set(names) 95 | 96 | XCTAssertEqual(namesSet, expectedNamesSet) 97 | XCTAssertFalse(namesSet.contains("fake.png")) 98 | 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /Tests/AltKitTests/FailableTestCase.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import Foundation 3 | 4 | /// 5 | /// A subclass of `XCTestCase` that fails in `setUp` and `tearDown`. 6 | /// 7 | 8 | class FailableTestCase: XCTestCase { 9 | 10 | override var continueAfterFailure: Bool { 11 | get { 12 | return false 13 | } 14 | set {} 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /Tests/AltKitTests/InfoPlistTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import Foundation 3 | import Files 4 | @testable import AltKit 5 | 6 | /// 7 | /// Tests the InfoPlist wrapper. 8 | /// 9 | 10 | class InfoPlistTests: FailableTestCase { 11 | 12 | /// The file containing valid alternate icons. 13 | var alternateIconsInfo: InfoPlist! 14 | 15 | /// The asset catalog. 16 | var assetCatalog: AssetCatalog! 17 | 18 | 19 | // MARK: - Lifecycle 20 | 21 | override func setUp() { 22 | 23 | let bundle = Bundle(for: InfoPlistTests.self) 24 | let alternateIconsInfoPath = bundle.bundlePath + "/Contents/Resources/TestFixtures/AlternateInfo.plist" 25 | let imagesAssetCatalogPath = bundle.bundlePath + "/Contents/Resources/TestFixtures/Images.xcassets" 26 | 27 | guard let alternateIconsInfoFile = try? File(path: alternateIconsInfoPath) else { 28 | XCTFail("Could not open the AlternateInfo.plist file.") 29 | return 30 | } 31 | 32 | guard let alternateIconsInfo = try? InfoPlist(file: alternateIconsInfoFile) else { 33 | XCTFail("Could not parse the AlternateInfo.plist file.") 34 | return 35 | } 36 | 37 | guard let assetCatalogFolder = try? Folder(path: imagesAssetCatalogPath) else { 38 | XCTFail("Could not open the Images.xcassets file.") 39 | return 40 | } 41 | 42 | self.alternateIconsInfo = alternateIconsInfo 43 | self.assetCatalog = AssetCatalog(folder: assetCatalogFolder) 44 | 45 | } 46 | 47 | override func tearDown() { 48 | alternateIconsInfo = nil 49 | assetCatalog = nil 50 | } 51 | 52 | 53 | // MARK: - Tests 54 | 55 | /// 56 | /// Tests that removing and adding bundle icons when updating works correctly. 57 | /// 58 | 59 | func testUpdatingExistingInfo() throws { 60 | 61 | let icons = try assetCatalog.listAppIconSets() 62 | alternateIconsInfo.update(alternateIcons: icons) 63 | 64 | guard let alternateIcons = alternateIconsInfo.parseIcons() else { 65 | XCTFail("Could not parse icons.") 66 | return 67 | } 68 | 69 | let expectedAlternateIcons: Set = [ 70 | BundleIcon(name: "AppIcon", files: makeFilesList(for: "AppIcon")), 71 | BundleIcon(name: "Light", files: makeFilesList(for: "Light")), 72 | BundleIcon(name: "Sombre", files: makeFilesList(for: "Sombre")) 73 | ] 74 | 75 | XCTAssertEqual(alternateIcons, expectedAlternateIcons) 76 | 77 | } 78 | 79 | func makeFilesList(for iconName: String) -> [String] { 80 | 81 | return [ 82 | "\(iconName)20x20@2x", 83 | "\(iconName)20x20@3x", 84 | "\(iconName)29x29", 85 | "\(iconName)29x29@2x", 86 | "\(iconName)29x29@3x", 87 | "\(iconName)40x40@2x", 88 | "\(iconName)40x40@3x", 89 | "\(iconName)57x57", 90 | "\(iconName)57x57@2x", 91 | "\(iconName)60x60@2x", 92 | "\(iconName)60x60@3x", 93 | "\(iconName)20x20~ipad", 94 | "\(iconName)20x20@2x~ipad", 95 | "\(iconName)29x29~ipad", 96 | "\(iconName)29x29@2x~ipad", 97 | "\(iconName)40x40~ipad", 98 | "\(iconName)40x40@2x~ipad", 99 | "\(iconName)50x50~ipad", 100 | "\(iconName)50x50@2x~ipad", 101 | "\(iconName)72x72@2x~ipad", 102 | "\(iconName)72x72~ipad", 103 | "\(iconName)76x76@2x~ipad", 104 | "\(iconName)76x76~ipad", 105 | "\(iconName)83.5x83.5@2x~ipad" 106 | ] 107 | 108 | } 109 | 110 | } 111 | 112 | // MARK: - Info Plist Parsing 113 | 114 | extension InfoPlist { 115 | 116 | /// 117 | /// Parses the icon information contained in the `Info.plist`. 118 | /// 119 | /// - returns: The alternate icons in the `Info.plist`. 120 | /// 121 | 122 | func parseIcons() -> Set? { 123 | 124 | guard let iphoneIcons = parseIcons(forVariant: InfoPlist.iconsKey) else { 125 | return nil 126 | } 127 | 128 | guard let ipadIcons = parseIcons(forVariant: InfoPlist.ipadIconsKey) else { 129 | return nil 130 | } 131 | 132 | let alternateIconsArray = merge([iphoneIcons, ipadIcons]) 133 | 134 | let alternateIcons = Set(alternateIconsArray) 135 | return alternateIcons 136 | 137 | } 138 | 139 | private func parseIcons(forVariant variant: String) -> [BundleIcon]? { 140 | 141 | guard let icons = infoDictionary[variant] as? [AnyHashable: Any] else { 142 | return nil 143 | } 144 | 145 | guard let alternateIconsDictionary = icons[InfoPlist.alternateIconsKey] as? [String: [AnyHashable: Any]] else { 146 | return nil 147 | } 148 | 149 | return alternateIconsDictionary.flatMap { 150 | 151 | guard let files = $0.value[InfoPlist.iconFilesKey] as? [String] else { 152 | return nil 153 | } 154 | 155 | return BundleIcon(name: $0.key, files: files) 156 | 157 | } 158 | 159 | } 160 | 161 | } 162 | -------------------------------------------------------------------------------- /Tests/AltKitTests/RunTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import Foundation 3 | import Files 4 | @testable import AltKit 5 | 6 | /// 7 | /// Tests the script execution. 8 | /// 9 | 10 | class RunTests: FailableTestCase { 11 | 12 | /// The arguments to use to test the script. 13 | var arguments: Script.Arguments! 14 | 15 | /// The Info.plist file before any modifications. 16 | var initialInfoPlistData: Data! 17 | 18 | /// The path to the XCTest bundle. 19 | var basePath: String! 20 | 21 | 22 | // MARK: - Lifecycle 23 | 24 | override func setUp() { 25 | 26 | let bundle = Bundle(for: InfoPlistTests.self) 27 | basePath = bundle.bundlePath + "/Contents/Resources/TestFixtures/" 28 | 29 | let infoPlistPath = bundle.bundlePath + "/Contents/Resources/TestFixtures/AppBundle/Info.plist" 30 | let catalogPath = bundle.bundlePath + "/Contents/Resources/TestFixtures/Images.xcassets" 31 | let appBundlePath = bundle.bundlePath + "/Contents/Resources/TestFixtures/AppBundle" 32 | 33 | do { 34 | 35 | let infoPlistFile = try File(path: infoPlistPath) 36 | let catalogFolder = try Folder(path: catalogPath) 37 | let appBundleFolder = try Folder(path: appBundlePath) 38 | 39 | let infoPlist = try InfoPlist(file: infoPlistFile) 40 | let catalog = AssetCatalog(folder: catalogFolder) 41 | 42 | initialInfoPlistData = try infoPlistFile.read() 43 | arguments = Script.Arguments(infoPlist: infoPlist, assetCatalog: catalog, appBundle: appBundleFolder) 44 | 45 | } catch { 46 | XCTFail("Could not set up: \(error)") 47 | } 48 | 49 | } 50 | 51 | override func tearDown() { 52 | 53 | do { 54 | 55 | for file in arguments.appBundle.files { 56 | try file.delete() 57 | } 58 | 59 | try arguments.infoPlist.file.write(data: initialInfoPlistData) 60 | 61 | arguments = nil 62 | basePath = nil 63 | 64 | } catch { 65 | XCTFail("Could not clean up.") 66 | } 67 | 68 | } 69 | 70 | 71 | // MARK: - Tests 72 | 73 | /// 74 | /// Tests that arguments can be read from the environment. 75 | /// 76 | 77 | func testReadArguments() throws { 78 | 79 | let readArguments = try Script.readArguments(resolvingAgainst: basePath) 80 | XCTAssertEqual(readArguments.appBundle, arguments.appBundle) 81 | XCTAssertEqual(readArguments.infoPlist, arguments.infoPlist) 82 | XCTAssertEqual(readArguments.assetCatalog, arguments.assetCatalog) 83 | 84 | } 85 | 86 | /// 87 | /// Tests running the script. 88 | /// 89 | 90 | func testRun() throws { 91 | 92 | // 1) Run the script 93 | 94 | let expectedAlternateIcons: Set = [ 95 | BundleIcon(name: "AppIcon", files: makeFilesList(for: "AppIcon")), 96 | BundleIcon(name: "Light", files: makeFilesList(for: "Light")), 97 | BundleIcon(name: "Sombre", files: makeFilesList(for: "Sombre")) 98 | ] 99 | 100 | try Script.run(with: arguments) 101 | 102 | // 2) Verify Info.plist 103 | 104 | let infoPlistPath = basePath + "AppBundle/Info.plist" 105 | let infoPlistFile = try File(path: infoPlistPath) 106 | let infoPlist = try InfoPlist(file: infoPlistFile) 107 | 108 | guard let iconsInInfoPlistAfterRun = infoPlist.parseIcons() else { 109 | XCTFail("Icons section not found in Info.plist") 110 | return 111 | } 112 | 113 | XCTAssertEqual(iconsInInfoPlistAfterRun, expectedAlternateIcons) 114 | 115 | // 3) Verify the copied files 116 | 117 | let iconFileNames = try arguments.assetCatalog.listAppIconSets().map { 118 | $0.enumerateImageFiles(unique: false) { _ in return true }.map { $0.destination } 119 | } 120 | 121 | let expectedIconFiles = merge(iconFileNames) 122 | 123 | for expectedIconFile in expectedIconFiles { 124 | XCTAssertTrue(arguments.appBundle.containsFile(named: expectedIconFile), "The '\(expectedIconFile)' file wasn't copied") 125 | } 126 | 127 | // 4) Verified Deleted Files 128 | 129 | let deletedIconPath = basePath + "AppBundle/AppIconOld@2x.png" 130 | XCTAssertFalse(FileManager.default.fileExists(atPath: deletedIconPath)) 131 | 132 | } 133 | 134 | func makeFilesList(for iconName: String) -> [String] { 135 | 136 | return [ 137 | "\(iconName)20x20@2x.png", 138 | "\(iconName)20x20@3x.png", 139 | "\(iconName)29x29.png", 140 | "\(iconName)29x29@2x.png", 141 | "\(iconName)29x29@3x.png", 142 | "\(iconName)40x40@2x.png", 143 | "\(iconName)40x40@3x.png", 144 | "\(iconName)57x57.png", 145 | "\(iconName)57x57@2x.png", 146 | "\(iconName)60x60@2x.png", 147 | "\(iconName)60x60@3x.png", 148 | "\(iconName)20x20~ipad.png", 149 | "\(iconName)20x20@2x~ipad.png", 150 | "\(iconName)29x29~ipad.png", 151 | "\(iconName)29x29@2x~ipad.png", 152 | "\(iconName)40x40~ipad.png", 153 | "\(iconName)40x40@2x~ipad.png", 154 | "\(iconName)50x50~ipad.png", 155 | "\(iconName)50x50@2x~ipad.png", 156 | "\(iconName)72x72@2x~ipad.png", 157 | "\(iconName)72x72~ipad.png", 158 | "\(iconName)76x76@2x~ipad.png", 159 | "\(iconName)76x76~ipad.png", 160 | "\(iconName)83.5x83.5@2x~ipad.png" 161 | ] 162 | 163 | } 164 | 165 | } 166 | -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cp -f embed-alternate-icons "/usr/local/bin/embed-alternate-icons" --------------------------------------------------------------------------------