├── .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 | [](https://travis-ci.org/alexaubry/alternate-icons)
4 | []()
5 | []()
6 | []()
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"
--------------------------------------------------------------------------------