├── .gitignore
├── Unused
├── Unused
│ ├── en.lproj
│ │ ├── InfoPlist.strings
│ │ ├── Credits.rtfd
│ │ │ └── TXT.rtf
│ │ ├── Localizable.strings
│ │ └── MainMenu.xib
│ ├── fr.lproj
│ │ ├── InfoPlist.strings
│ │ ├── Localizable.strings
│ │ └── Credits.rtfd
│ │ │ └── TXT.rtf
│ ├── Icon.icns
│ ├── Images.xcassets
│ │ └── AppIcon.appiconset
│ │ │ ├── icon_16x16.png
│ │ │ ├── icon_32x32.png
│ │ │ ├── icon_128x128.png
│ │ │ ├── icon_256x256-1.png
│ │ │ ├── icon_256x256.png
│ │ │ ├── icon_32x32-1.png
│ │ │ ├── icon_512x512-1.png
│ │ │ ├── icon_512x512.png
│ │ │ └── Contents.json
│ ├── Unused-Prefix.pch
│ ├── main.m
│ ├── CONTRIBUTORS
│ ├── Unused-Info.plist
│ ├── FileUtil.h
│ ├── FileUtil.m
│ ├── Searcher.h
│ ├── UnusedAppDelegate.h
│ ├── UnusedAppDelegate.m
│ └── Searcher.m
└── Unused.xcodeproj
│ ├── xcuserdata
│ └── jeff.xcuserdatad
│ │ ├── xcdebugger
│ │ └── Breakpoints.xcbkptlist
│ │ └── xcschemes
│ │ ├── xcschememanagement.plist
│ │ └── Unused.xcscheme
│ ├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcuserdata
│ │ └── jeff.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
│ └── project.pbxproj
└── README
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | xcuserdata
3 | *.xccheckout
4 |
--------------------------------------------------------------------------------
/Unused/Unused/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/Unused/Unused/fr.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /* Localized versions of Info.plist keys */
2 |
3 |
--------------------------------------------------------------------------------
/Unused/Unused/Icon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeffhodnett/Unused/HEAD/Unused/Unused/Icon.icns
--------------------------------------------------------------------------------
/Unused/Unused/fr.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 |
2 | /* Search */
3 | "Search" = "Fouille";
4 | "Searching" = "Fouille...";
5 |
--------------------------------------------------------------------------------
/Unused/Unused/Images.xcassets/AppIcon.appiconset/icon_16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeffhodnett/Unused/HEAD/Unused/Unused/Images.xcassets/AppIcon.appiconset/icon_16x16.png
--------------------------------------------------------------------------------
/Unused/Unused/Images.xcassets/AppIcon.appiconset/icon_32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeffhodnett/Unused/HEAD/Unused/Unused/Images.xcassets/AppIcon.appiconset/icon_32x32.png
--------------------------------------------------------------------------------
/Unused/Unused/Images.xcassets/AppIcon.appiconset/icon_128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeffhodnett/Unused/HEAD/Unused/Unused/Images.xcassets/AppIcon.appiconset/icon_128x128.png
--------------------------------------------------------------------------------
/Unused/Unused/Images.xcassets/AppIcon.appiconset/icon_256x256-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeffhodnett/Unused/HEAD/Unused/Unused/Images.xcassets/AppIcon.appiconset/icon_256x256-1.png
--------------------------------------------------------------------------------
/Unused/Unused/Images.xcassets/AppIcon.appiconset/icon_256x256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeffhodnett/Unused/HEAD/Unused/Unused/Images.xcassets/AppIcon.appiconset/icon_256x256.png
--------------------------------------------------------------------------------
/Unused/Unused/Images.xcassets/AppIcon.appiconset/icon_32x32-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeffhodnett/Unused/HEAD/Unused/Unused/Images.xcassets/AppIcon.appiconset/icon_32x32-1.png
--------------------------------------------------------------------------------
/Unused/Unused/Images.xcassets/AppIcon.appiconset/icon_512x512-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeffhodnett/Unused/HEAD/Unused/Unused/Images.xcassets/AppIcon.appiconset/icon_512x512-1.png
--------------------------------------------------------------------------------
/Unused/Unused/Images.xcassets/AppIcon.appiconset/icon_512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeffhodnett/Unused/HEAD/Unused/Unused/Images.xcassets/AppIcon.appiconset/icon_512x512.png
--------------------------------------------------------------------------------
/Unused/Unused.xcodeproj/xcuserdata/jeff.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/Unused/Unused/Unused-Prefix.pch:
--------------------------------------------------------------------------------
1 | //
2 | // Prefix header for all source files of the 'Unused' target in the 'Unused' project
3 | //
4 |
5 | #ifdef __OBJC__
6 | #import
7 | #endif
8 |
--------------------------------------------------------------------------------
/Unused/Unused.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Unused/Unused.xcodeproj/project.xcworkspace/xcuserdata/jeff.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jeffhodnett/Unused/HEAD/Unused/Unused.xcodeproj/project.xcworkspace/xcuserdata/jeff.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Unused/Unused/main.m:
--------------------------------------------------------------------------------
1 | //
2 | // main.m
3 | // Unused
4 | //
5 | // Created by Jeff Hodnett on 19/11/2011.
6 | // Copyright 2011 __MyCompanyName__. All rights reserved.
7 | //
8 |
9 | #import
10 |
11 | int main(int argc, char *argv[])
12 | {
13 | return NSApplicationMain(argc, (const char **)argv);
14 | }
15 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | Unused - Mac App
2 | ================
3 |
4 | version 1.0
5 |
6 | Created by: Jeff Hodnett
7 | jefers@gmail.com
8 | http://www.jeffhodnett.com
9 |
10 | Use this useful utility tool to check what image resources are not being used in your Xcode projects.
11 | Very useful to reduce your bundle size by showing you what images are not used!
12 |
13 | Full project info here:
14 | http://jeffhodnett.github.io/Unused/
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/Unused/Unused/CONTRIBUTORS:
--------------------------------------------------------------------------------
1 |
2 | THANK YOU!
3 |
4 | Many thanks for all the hard work of the contributors, without your interest this open source project it would not continue to improve. Please add your name to the list of contributors below so you can get the credit you deserve.
5 |
6 | Thanks,
7 | Jeff
8 | @jeffhodnett
9 |
10 |
11 | CONTRIBUTORS:
12 |
13 | - Fábio Bernardo
14 | - Andrey Toropchin
15 | - Iain Delaney
16 | - BrianSemiglia
17 | - guykogus
18 | - RolandasRazma
19 | - neoman-v
20 | - cytryn
21 | - Asynchrony Dev
22 | - laughingMan
--------------------------------------------------------------------------------
/Unused/Unused.xcodeproj/xcuserdata/jeff.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | Unused.xcscheme
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 1F55B4A21478097A008A4B0E
16 |
17 | primary
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/Unused/Unused/en.lproj/Credits.rtfd/TXT.rtf:
--------------------------------------------------------------------------------
1 | {\rtf1\ansi\ansicpg1252\cocoartf1344\cocoasubrtf720
2 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fnil\fcharset0 Menlo-Regular;}
3 | {\colortbl;\red255\green255\blue255;\red14\green14\blue255;}
4 | \paperw11900\paperh16840\vieww9600\viewh8400\viewkind0
5 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
6 |
7 | \f0\b\fs24 \cf0 Developed by:\
8 |
9 | \b0 Jeff Hodnett\
10 | http://www.jeffhodnett.com\
11 |
12 | \b \
13 | \pard\tx577\pardeftab577\pardirnatural
14 | {\field{\*\fldinst{HYPERLINK "https://github.com/jeffhodnett/Unused"}}{\fldrslt
15 | \f1\b0 \cf2 \CocoaLigature0 https://github.com/jeffhodnett/Unused}}}
--------------------------------------------------------------------------------
/Unused/Unused/fr.lproj/Credits.rtfd/TXT.rtf:
--------------------------------------------------------------------------------
1 | {\rtf1\ansi\ansicpg1252\cocoartf1344\cocoasubrtf720
2 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;\f1\fnil\fcharset0 Menlo-Regular;}
3 | {\colortbl;\red255\green255\blue255;\red14\green14\blue255;}
4 | \paperw11900\paperh16840\vieww9600\viewh8400\viewkind0
5 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
6 |
7 | \f0\b\fs24 \cf0 Developed by:\
8 |
9 | \b0 Jeff Hodnett\
10 | http://www.jeffhodnett.com\
11 |
12 | \b \
13 | \pard\tx577\pardeftab577\pardirnatural
14 | {\field{\*\fldinst{HYPERLINK "https://github.com/jeffhodnett/Unused"}}{\fldrslt
15 | \f1\b0 \cf2 \CocoaLigature0 https://github.com/jeffhodnett/Unused}}}
--------------------------------------------------------------------------------
/Unused/Unused/en.lproj/Localizable.strings:
--------------------------------------------------------------------------------
1 |
2 | /* Search */
3 | "Search" = "Search";
4 | "Searching" = "Searching...";
5 | "CompletedResultMessage" = "Completed - Found %ld - Size %@";
6 |
7 | /* Export */
8 | "ExportSummaryTitle" = "Unused Files in project %@\n\n";
9 | "ExportCompleteTitle" = "Export Complete";
10 | "ExportCompleteSubtitle" = "The results have been exported successfully";
11 | "ExportErrorTitle" = "Export Error";
12 | "ExportErrorSubtitle" = "There was an error exporting the results";
13 |
14 | /* Errors */
15 | "MissingPathErrorTitle" = "No Project Folder Selected";
16 | "InvalidPathErrorTitle" = "Invalid Project Folder";
17 | "ProjectFolderPathErrorMessage" = "\nPlease select a valid project folder";
18 |
--------------------------------------------------------------------------------
/Unused/Unused/Unused-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | ${EXECUTABLE_NAME}
9 | CFBundleIdentifier
10 | com.jeffhodnett.$(PRODUCT_NAME:rfc1034identifier)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | ${PRODUCT_NAME}
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.1
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSApplicationCategoryType
24 | public.app-category.utilities
25 | LSMinimumSystemVersion
26 | ${MACOSX_DEPLOYMENT_TARGET}
27 | NSHumanReadableCopyright
28 | Copyright © 2013 Seamonster Ltd. All rights reserved.
29 | NSMainNibFile
30 | MainMenu
31 | NSPrincipalClass
32 | NSApplication
33 |
34 |
35 |
--------------------------------------------------------------------------------
/Unused/Unused/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "16x16",
5 | "idiom" : "mac",
6 | "filename" : "icon_16x16.png",
7 | "scale" : "1x"
8 | },
9 | {
10 | "size" : "16x16",
11 | "idiom" : "mac",
12 | "filename" : "icon_32x32.png",
13 | "scale" : "2x"
14 | },
15 | {
16 | "size" : "32x32",
17 | "idiom" : "mac",
18 | "filename" : "icon_32x32-1.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "idiom" : "mac",
23 | "size" : "32x32",
24 | "scale" : "2x"
25 | },
26 | {
27 | "size" : "128x128",
28 | "idiom" : "mac",
29 | "filename" : "icon_128x128.png",
30 | "scale" : "1x"
31 | },
32 | {
33 | "size" : "128x128",
34 | "idiom" : "mac",
35 | "filename" : "icon_256x256-1.png",
36 | "scale" : "2x"
37 | },
38 | {
39 | "size" : "256x256",
40 | "idiom" : "mac",
41 | "filename" : "icon_256x256.png",
42 | "scale" : "1x"
43 | },
44 | {
45 | "size" : "256x256",
46 | "idiom" : "mac",
47 | "filename" : "icon_512x512.png",
48 | "scale" : "2x"
49 | },
50 | {
51 | "size" : "512x512",
52 | "idiom" : "mac",
53 | "filename" : "icon_512x512-1.png",
54 | "scale" : "1x"
55 | },
56 | {
57 | "idiom" : "mac",
58 | "size" : "512x512",
59 | "scale" : "2x"
60 | }
61 | ],
62 | "info" : {
63 | "version" : 1,
64 | "author" : "xcode"
65 | }
66 | }
--------------------------------------------------------------------------------
/Unused/Unused/FileUtil.h:
--------------------------------------------------------------------------------
1 | //
2 | // FileUtil.h
3 | // Unused
4 | // https://github.com/jeffhodnett/Unused
5 | //
6 | // Copyright (c) 2015 Jeff Hodnett
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 |
27 | #import
28 |
29 | /**
30 | * File util helper class
31 | */
32 | @interface FileUtil : NSObject
33 |
34 | /**
35 | * Return the nice formatted string for a file size
36 | * i.e input = 1024 output = 1 KB
37 | *
38 | * @param fileSize The file size integer
39 | *
40 | * @return The formatted string descriptor for the size value
41 | */
42 | + (NSString *)stringFromFileSize:(int)fileSize;
43 |
44 | /**
45 | * Return all the image paths in the provided directory
46 | *
47 | * This includes searching for image files like
48 | * .jpg, .jpeg, .png, .gif
49 | *
50 | * @param directoryPath The search path
51 | *
52 | * @return The array of image paths
53 | */
54 | + (NSArray *)imageFilesInDirectory:(NSString *)directoryPath;
55 |
56 | @end
57 |
--------------------------------------------------------------------------------
/Unused/Unused.xcodeproj/xcuserdata/jeff.xcuserdatad/xcschemes/Unused.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
53 |
54 |
60 |
61 |
62 |
63 |
64 |
65 |
73 |
74 |
80 |
81 |
82 |
83 |
85 |
86 |
89 |
90 |
91 |
--------------------------------------------------------------------------------
/Unused/Unused/FileUtil.m:
--------------------------------------------------------------------------------
1 | //
2 | // FileUtil.m
3 | // Unused
4 | // https://github.com/jeffhodnett/Unused
5 | //
6 | // Copyright (c) 2015 Jeff Hodnett
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 |
27 | #import "FileUtil.h"
28 |
29 | @implementation FileUtil
30 |
31 | + (NSString *)stringFromFileSize:(int)fileSize {
32 | if (fileSize < 1023) {
33 | return([NSString stringWithFormat:@"%i bytes", fileSize]);
34 | }
35 |
36 | float floatSize = fileSize / 1024;
37 | if (floatSize < 1023) {
38 | return([NSString stringWithFormat:@"%1.1f KB", floatSize]);
39 | }
40 |
41 | floatSize = floatSize / 1024;
42 | if (floatSize < 1023) {
43 | return([NSString stringWithFormat:@"%1.1f MB", floatSize]);
44 | }
45 |
46 | floatSize = floatSize / 1024;
47 | return([NSString stringWithFormat:@"%1.1f GB",floatSize]);
48 | }
49 |
50 | + (NSArray *)imageFilesInDirectory:(NSString *)directoryPath {
51 |
52 | NSMutableArray *images = [NSMutableArray array];
53 |
54 | // jpg
55 | NSArray *jpg = [self searchDirectory:directoryPath forFiletype:@"jpg"];
56 | [images addObjectsFromArray:jpg];
57 |
58 | // jpeg
59 | NSArray *jpeg = [self searchDirectory:directoryPath forFiletype:@"jpeg"];
60 | [images addObjectsFromArray:jpeg];
61 |
62 | // png
63 | NSArray *png = [self searchDirectory:directoryPath forFiletype:@"png"];
64 | [images addObjectsFromArray:png];
65 |
66 | // gif
67 | NSArray *gif = [self searchDirectory:directoryPath forFiletype:@"gif"];
68 | [images addObjectsFromArray:gif];
69 |
70 | return images;
71 | }
72 |
73 | + (NSArray *)searchDirectory:(NSString *)directoryPath forFiletype:(NSString *)filetype {
74 | // Create a find task
75 | NSTask *task = [[NSTask alloc] init];
76 | [task setLaunchPath: @"/usr/bin/find"];
77 |
78 | // Search for all png files
79 | NSArray *argvals = [NSArray arrayWithObjects:directoryPath,@"-name",[NSString stringWithFormat:@"*.%@", filetype], nil];
80 | [task setArguments: argvals];
81 |
82 | NSPipe *pipe = [NSPipe pipe];
83 | [task setStandardOutput: pipe];
84 | NSFileHandle *file = [pipe fileHandleForReading];
85 |
86 | // Run task
87 | [task launch];
88 |
89 | // Read the response
90 | NSData *data = [file readDataToEndOfFile];
91 | NSString *string = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
92 |
93 | // See if we can create a lines array
94 | NSArray *lines = [string componentsSeparatedByString:@"\n"];
95 |
96 | return lines;
97 | }
98 |
99 | @end
100 |
--------------------------------------------------------------------------------
/Unused/Unused/Searcher.h:
--------------------------------------------------------------------------------
1 | //
2 | // Searcher.h
3 | // Unused
4 | // https://github.com/jeffhodnett/Unused
5 | //
6 | // Copyright (c) 2015 Jeff Hodnett
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 |
27 | #import
28 |
29 | @class Searcher;
30 |
31 | /**
32 | * The searcher delegate
33 | */
34 | @protocol SearcherDelegate
35 |
36 | @optional
37 | /**
38 | * The searcher did begin searching
39 | *
40 | * @param searcher The searcher object
41 | */
42 | - (void)searcherDidStartSearch:(Searcher *)searcher;
43 |
44 | /**
45 | * The searcher did find an unused image during its search
46 | *
47 | * @param searcher The searcher object
48 | * @param imagePath The unused image path
49 | */
50 | - (void)searcher:(Searcher *)searcher didFindUnusedImage:(NSString *)imagePath;
51 |
52 | /**
53 | * The searcher did finish searching
54 | *
55 | * @param searcher The searcher object
56 | * @param results The unused image path results
57 | */
58 | - (void)searcher:(Searcher *)searcher didFinishSearch:(NSArray *)results;
59 |
60 | @end
61 |
62 | /**
63 | * The searcher class
64 | * Use this object to search for un-used image files in your xcode projects
65 | */
66 | @interface Searcher : NSObject
67 |
68 | /**
69 | * The searcher delegate
70 | */
71 | @property (assign) id delegate;
72 |
73 | /**
74 | * The project search path
75 | */
76 | @property (copy) NSString *projectPath;
77 |
78 | /**
79 | * Include .m files in the search
80 | */
81 | @property (nonatomic) BOOL mSearch;
82 |
83 | /**
84 | * Include .xib files in the search
85 | */
86 | @property (nonatomic) BOOL xibSearch;
87 |
88 | /**
89 | * Include .storyboard files in the search
90 | */
91 | @property (nonatomic) BOOL storyboardSearch;
92 |
93 | /**
94 | * Include .cpp files in the search
95 | */
96 | @property (nonatomic) BOOL cppSearch;
97 |
98 | /**
99 | * Include .h files in the search
100 | */
101 | @property (nonatomic) BOOL headerSearch;
102 |
103 | /**
104 | * Include .html files in the search
105 | */
106 | @property (nonatomic) BOOL htmlSearch;
107 |
108 | /**
109 | * Include .mm files in the search
110 | */
111 | @property (nonatomic) BOOL mmSearch;
112 |
113 | /**
114 | * Include .plist files in the search
115 | */
116 | @property (nonatomic) BOOL plistSearch;
117 |
118 | /**
119 | * Include .css files in the search
120 | */
121 | @property (nonatomic) BOOL cssSearch;
122 |
123 | /**
124 | * Include .swift files in the search
125 | */
126 | @property (nonatomic) BOOL swiftSearch;
127 |
128 | /**
129 | * Include image enum variant filtering in the search
130 | */
131 | @property (nonatomic) BOOL enumFilter;
132 |
133 | /**
134 | * Start the search
135 | */
136 | - (void)start;
137 |
138 | /**
139 | * Stop the search
140 | */
141 | - (void)stop;
142 |
143 | @end
144 |
--------------------------------------------------------------------------------
/Unused/Unused/UnusedAppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | // UnusedAppDelegate.h
3 | // Unused
4 | // A Mac utility to show you unused resources in your xcode projects
5 | // https://github.com/jeffhodnett/Unused
6 | //
7 | // Copyright (c) 2015 Jeff Hodnett
8 | //
9 | // Permission is hereby granted, free of charge, to any person obtaining a copy
10 | // of this software and associated documentation files (the "Software"), to deal
11 | // in the Software without restriction, including without limitation the rights
12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 | // copies of the Software, and to permit persons to whom the Software is
14 | // furnished to do so, subject to the following conditions:
15 | //
16 | // The above copyright notice and this permission notice shall be included in all
17 | // copies or substantial portions of the Software.
18 | //
19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 | // SOFTWARE.
26 | //
27 |
28 | #import
29 |
30 | /**
31 | * The application delegate
32 | */
33 | @interface UnusedAppDelegate : NSObject
34 |
35 | // ------ Outlets ------
36 | /**
37 | * The main window
38 | */
39 | @property (assign) IBOutlet NSWindow *window;
40 |
41 | /**
42 | * The results table view
43 | */
44 | @property (assign) IBOutlet NSTableView *resultsTableView;
45 |
46 | /**
47 | * The loading indicator view
48 | */
49 | @property (assign) IBOutlet NSProgressIndicator *processIndicator;
50 |
51 | /**
52 | * The status text label
53 | */
54 | @property (assign) IBOutlet NSTextField *statusLabel;
55 |
56 | /**
57 | * The browse button
58 | */
59 | @property (assign) IBOutlet NSButton *browseButton;
60 |
61 | /**
62 | * The search path text field
63 | */
64 | @property (assign) IBOutlet NSTextField *pathTextField;
65 |
66 | /**
67 | * The search action button
68 | */
69 | @property (assign) IBOutlet NSButton *searchButton;
70 |
71 | /**
72 | * The export button
73 | */
74 | @property (assign) IBOutlet NSButton *exportButton;
75 |
76 | /**
77 | * The .m file checkbox
78 | */
79 | @property (assign) IBOutlet NSButton *mCheckbox;
80 |
81 | /**
82 | * The .xib file checkbox
83 | */
84 | @property (assign) IBOutlet NSButton *xibCheckbox;
85 |
86 | /**
87 | * The .storyboard file checkbox
88 | */
89 | @property (assign) IBOutlet NSButton *sbCheckbox;
90 |
91 | /**
92 | * The .cpp file checkbox
93 | */
94 | @property (assign) IBOutlet NSButton *cppCheckbox;
95 |
96 | /**
97 | * The .h file checkbox
98 | */
99 | @property (assign) IBOutlet NSButton *headerCheckbox;
100 |
101 | /**
102 | * The .html file checkbox
103 | */
104 | @property (assign) IBOutlet NSButton *htmlCheckbox;
105 |
106 | /**
107 | * The .mm file checkbox
108 | */
109 | @property (assign) IBOutlet NSButton *mmCheckbox;
110 |
111 | /**
112 | * The .plist file checkbox
113 | */
114 | @property (assign) IBOutlet NSButton *plistCheckbox;
115 |
116 | /**
117 | * The .css file checkbox
118 | */
119 | @property (assign) IBOutlet NSButton *cssCheckbox;
120 |
121 | /**
122 | * The .swift file checkbox
123 | */
124 | @property (assign) IBOutlet NSButton *swiftCheckbox;
125 |
126 | /**
127 | * The enum checkbox
128 | */
129 | @property (assign) IBOutlet NSButton *enumCheckbox;
130 |
131 | // ------ Actions ------
132 | /**
133 | * The browse for xcode project action
134 | *
135 | * @param sender The browse button
136 | */
137 | - (IBAction)browseButtonSelected:(id)sender;
138 |
139 | /**
140 | * Start the search process
141 | *
142 | * @param sender The search button
143 | */
144 | - (IBAction)startSearch:(id)sender;
145 |
146 | /**
147 | * Export the results to a file
148 | *
149 | * @param sender The export button
150 | */
151 | - (IBAction)exportButtonSelected:(id)sender;
152 |
153 | @end
154 |
--------------------------------------------------------------------------------
/Unused/Unused/UnusedAppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | // UnusedAppDelegate.m
3 | // Unused
4 | // https://github.com/jeffhodnett/Unused
5 | //
6 | // Copyright (c) 2015 Jeff Hodnett
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 |
27 | #import "UnusedAppDelegate.h"
28 | #import "Searcher.h"
29 | #import "FileUtil.h"
30 |
31 | @interface UnusedAppDelegate ()
32 |
33 | @property (nonatomic, strong) NSMutableArray *results;
34 | @property (nonatomic, strong) Searcher *searcher;
35 |
36 | // Handle the ui updates
37 | - (void)setUIEnabled:(BOOL)state;
38 |
39 | @end
40 |
41 | // Constant strings
42 | static NSString *const kTableColumnImageIcon = @"ImageIcon";
43 | static NSString *const kTableColumnImageShortName = @"ImageShortName";
44 |
45 | @implementation UnusedAppDelegate
46 |
47 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
48 | // Setup the results array
49 | _results = [[NSMutableArray alloc] init];
50 |
51 | // Setup double click
52 | [_resultsTableView setDoubleAction:@selector(tableViewDoubleClicked)];
53 |
54 | // Setup labels
55 | [_statusLabel setTextColor:[NSColor lightGrayColor]];
56 |
57 | // Setup search button
58 | [_searchButton setBezelStyle:NSRoundedBezelStyle];
59 | [_searchButton setKeyEquivalent:@"\r"];
60 |
61 | // Setup the searcher
62 | self.searcher = [[Searcher alloc] init];
63 | self.searcher.delegate = self;
64 | }
65 |
66 | #pragma mark - Actions
67 | - (IBAction)browseButtonSelected:(id)sender {
68 | // Show an open panel
69 | NSOpenPanel *openPanel = [NSOpenPanel openPanel];
70 | [openPanel setCanChooseDirectories:YES];
71 | [openPanel setCanChooseFiles:NO];
72 |
73 | BOOL okButtonPressed = ([openPanel runModal] == NSModalResponseOK);
74 | if (okButtonPressed) {
75 | // Update the path text field
76 | NSString *path = [[openPanel directoryURL] path];
77 | [self.pathTextField setStringValue:path];
78 | }
79 | }
80 |
81 | - (IBAction)exportButtonSelected:(id)sender {
82 | NSSavePanel *save = [NSSavePanel savePanel];
83 | [save setAllowedFileTypes:[NSArray arrayWithObject:@"txt"]];
84 |
85 | BOOL okButtonPressed = ([save runModal] == NSModalResponseOK);
86 | if (okButtonPressed) {
87 | NSString *selectedFile = [[save URL] path];
88 |
89 | NSMutableString *outputResults = [[NSMutableString alloc] init];
90 | NSString *projectPath = [self.pathTextField stringValue];
91 | [outputResults appendFormat:NSLocalizedString(@"ExportSummaryTitle", @""), projectPath];
92 |
93 | for (NSString *path in _results) {
94 | [outputResults appendFormat:@"%@\n",path];
95 | }
96 |
97 | // Output
98 | NSError *writeError = nil;
99 | [outputResults writeToFile:selectedFile atomically:YES encoding:NSUTF8StringEncoding error:&writeError];
100 |
101 | // Check write result
102 | if (writeError == nil) {
103 | [self showAlertWithStyle:NSInformationalAlertStyle title:NSLocalizedString(@"ExportCompleteTitle", @"") subtitle:NSLocalizedString(@"ExportCompleteSubtitle", @"")];
104 | } else {
105 | NSLog(@"Unused write error:: %@", writeError);
106 | [self showAlertWithStyle:NSCriticalAlertStyle title:NSLocalizedString(@"ExportErrorTitle", @"") subtitle:NSLocalizedString(@"ExportErrorSubtitle", @"")];
107 | }
108 | }
109 | }
110 |
111 | - (IBAction)startSearch:(id)sender {
112 | // Check if user has selected or entered a path
113 | NSString *projectPath = [self.pathTextField stringValue];
114 | BOOL isPathEmpty = [projectPath isEqualToString:@""];
115 | if (isPathEmpty) {
116 | [self showAlertWithStyle:NSWarningAlertStyle title:NSLocalizedString(@"MissingPathErrorTitle", @"") subtitle:NSLocalizedString(@"ProjectFolderPathErrorMessage", @"")];
117 |
118 | return;
119 | }
120 |
121 | // Check the path exists
122 | BOOL pathExists = [[NSFileManager defaultManager] fileExistsAtPath:projectPath];
123 | if (!pathExists) {
124 | [self showAlertWithStyle:NSWarningAlertStyle title:NSLocalizedString(@"InvalidPathErrorTitle", @"") subtitle:NSLocalizedString(@"ProjectFolderPathErrorMessage", @"")];
125 |
126 | return;
127 | }
128 |
129 | // Reset
130 | [self.results removeAllObjects];
131 | [self.resultsTableView reloadData];
132 |
133 | // Start the ui
134 | [self setUIEnabled:NO];
135 |
136 | // Pass search folder
137 | self.searcher.projectPath = projectPath;
138 |
139 | // Pass settings
140 | self.searcher.mSearch = [self.mCheckbox state];
141 | self.searcher.xibSearch = [self.xibCheckbox state];
142 | self.searcher.storyboardSearch = [self.sbCheckbox state];
143 | self.searcher.cppSearch = [self.cppCheckbox state];
144 | self.searcher.headerSearch = [self.headerCheckbox state];
145 | self.searcher.htmlSearch = [self.htmlCheckbox state];
146 | self.searcher.mmSearch = [self.mmCheckbox state];
147 | self.searcher.plistSearch = [self.plistCheckbox state];
148 | self.searcher.cssSearch = [self.cssCheckbox state];
149 | self.searcher.swiftSearch = [self.swiftCheckbox state];
150 | self.searcher.enumFilter = [self.enumCheckbox state];
151 |
152 | // Start the search
153 | [self.searcher start];
154 | }
155 |
156 | #pragma mark - Helpers
157 | - (void)showAlertWithStyle:(NSAlertStyle)style title:(NSString *)title subtitle:(NSString *)subtitle {
158 | NSAlert *alert = [[NSAlert alloc] init];
159 | alert.alertStyle = style;
160 | [alert setMessageText:title];
161 | [alert setInformativeText:subtitle];
162 | [alert runModal];
163 | }
164 |
165 | - (void)scrollTableView:(NSTableView *)tableView toBottom:(BOOL)bottom {
166 | if (bottom) {
167 | NSInteger numberOfRows = [tableView numberOfRows];
168 | if (numberOfRows > 0) {
169 | [tableView scrollRowToVisible:numberOfRows - 1];
170 | }
171 | } else {
172 | [tableView scrollRowToVisible:0];
173 | }
174 | }
175 |
176 | - (void)setUIEnabled:(BOOL)state {
177 | // Individual
178 | if (state) {
179 | [_searchButton setTitle:NSLocalizedString(@"Search", @"")];
180 | [_searchButton setKeyEquivalent:@"\r"];
181 | [_processIndicator stopAnimation:self];
182 | } else {
183 | [self.searchButton setKeyEquivalent:@""];
184 | [_processIndicator startAnimation:self];
185 | [_statusLabel setStringValue:NSLocalizedString(@"Searching", @"")];
186 | }
187 |
188 | // Button groups
189 | [_searchButton setEnabled:state];
190 | [_processIndicator setHidden:state];
191 | [_mCheckbox setEnabled:state];
192 | [_xibCheckbox setEnabled:state];
193 | [_sbCheckbox setEnabled:state];
194 | [_cppCheckbox setEnabled:state];
195 | [_mmCheckbox setEnabled:state];
196 | [_headerCheckbox setEnabled:state];
197 | [_htmlCheckbox setEnabled:state];
198 | [_plistCheckbox setEnabled:state];
199 | [_cssCheckbox setEnabled:state];
200 | [_swiftCheckbox setEnabled:state];
201 | [_browseButton setEnabled:state];
202 | [_pathTextField setEnabled:state];
203 | [_exportButton setHidden:!state];
204 | }
205 |
206 | #pragma mark -
207 | - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
208 | return [self.results count];
209 | }
210 |
211 | - (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)rowIndex {
212 | // Get the unused image
213 | NSString *pngPath = [self.results objectAtIndex:rowIndex];
214 |
215 | // Check the column
216 | NSString *columnIdentifier = [tableColumn identifier];
217 | if ([columnIdentifier isEqualToString:kTableColumnImageIcon]) {
218 | return [[NSImage alloc] initByReferencingFile:pngPath];
219 | } else if ([columnIdentifier isEqualToString:kTableColumnImageShortName]) {
220 | return [pngPath lastPathComponent];
221 | }
222 |
223 | return pngPath;
224 | }
225 |
226 | - (void)tableViewDoubleClicked {
227 | // Open finder
228 | NSString *path = [self.results objectAtIndex:[self.resultsTableView clickedRow]];
229 | [[NSWorkspace sharedWorkspace] selectFile:path inFileViewerRootedAtPath:nil];
230 | }
231 |
232 | #pragma mark -
233 | - (void)searcherDidStartSearch:(Searcher *)searcher {
234 | }
235 |
236 | - (void)searcher:(Searcher *)searcher didFindUnusedImage:(NSString *)imagePath {
237 |
238 | // Add and reload
239 | [self.results addObject:imagePath];
240 |
241 | // Reload
242 | [self.resultsTableView reloadData];
243 |
244 | // Scroll to the bottom
245 | [self scrollTableView:self.resultsTableView toBottom:YES];
246 | }
247 |
248 | - (void)searcher:(Searcher *)searcher didFinishSearch:(NSArray *)results {
249 |
250 | // Ensure all data is displayed
251 | [self.resultsTableView reloadData];
252 |
253 | // Calculate how much file size we saved and update the label
254 | int fileSize = 0;
255 | for (NSString *path in _results) {
256 | fileSize += [[[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil] fileSize];
257 | }
258 | [self.statusLabel setStringValue:[NSString stringWithFormat:NSLocalizedString(@"CompletedResultMessage", @""), (unsigned long)[_results count], [FileUtil stringFromFileSize:fileSize]]];
259 |
260 | // Enable the ui
261 | [self setUIEnabled:YES];
262 | }
263 |
264 | @end
265 |
--------------------------------------------------------------------------------
/Unused/Unused/Searcher.m:
--------------------------------------------------------------------------------
1 | //
2 | // Searcher.m
3 | // Unused
4 | // https://github.com/jeffhodnett/Unused
5 | //
6 | // Copyright (c) 2015 Jeff Hodnett
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 |
27 | #import "Searcher.h"
28 | #import "FileUtil.h"
29 |
30 | @interface Searcher () {
31 | @private
32 |
33 | // Arrays
34 | NSArray *_projectImageFiles;
35 | NSMutableArray *_results;
36 | NSMutableArray *_retinaImagePaths;
37 |
38 | NSOperationQueue *_queue;
39 | BOOL isSearching;
40 |
41 | // Stores the file data to avoid re-reading files, using a lock to make it thread-safe.
42 | NSMutableDictionary *_fileData;
43 | NSLock *_fileDataLock;
44 | }
45 |
46 | @end
47 |
48 | @implementation Searcher
49 |
50 | - (instancetype)init {
51 | if (self = [super init]) {
52 |
53 | // Setup the results array
54 | _results = [[NSMutableArray alloc] init];
55 |
56 | // Setup the retina images array
57 | _retinaImagePaths = [[NSMutableArray alloc] init];
58 |
59 | // Setup the queue
60 | _queue = [[NSOperationQueue alloc] init];
61 |
62 | // Setup data lock
63 | _fileData = [NSMutableDictionary new];
64 | _fileDataLock = [NSLock new];
65 | }
66 | return self;
67 | }
68 |
69 | - (void)start {
70 |
71 | // Start the search
72 | NSInvocationOperation *searchOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(runImageSearch:) object:self.projectPath];
73 | [_queue addOperation:searchOperation];
74 | }
75 |
76 | - (void)stop {
77 | #warning implement me!
78 | }
79 |
80 | - (void)runImageSearch:(NSString *)searchPath {
81 | // Start the search
82 | if (self.delegate && [self.delegate respondsToSelector:@selector(searcherDidStartSearch:)]) {
83 | [self.delegate searcherDidStartSearch:self];
84 | }
85 |
86 | // Find all the image files in the folder
87 | _projectImageFiles = [FileUtil imageFilesInDirectory:searchPath];
88 |
89 | NSArray *imageFiles = _projectImageFiles;
90 | if (self.enumFilter) {
91 | NSMutableArray *mutablePngFiles = [NSMutableArray arrayWithArray:imageFiles];
92 |
93 | // Trying to filter image names like: "Section_0.png", "Section_1.png", etc (these names can possibly be created by [NSString stringWithFormat:@"Section_%d", (int)] constructions) to just "Section_" item
94 | for (NSInteger index = 0, count = [mutablePngFiles count]; index < count; index++) {
95 | NSString *imageName = [mutablePngFiles objectAtIndex:index];
96 | NSRegularExpression *regExp = [NSRegularExpression regularExpressionWithPattern:@"[_-].*\\d.*.png" options:NSRegularExpressionCaseInsensitive error:nil];
97 | NSString *newImageName = [regExp stringByReplacingMatchesInString:imageName options:NSMatchingReportProgress range:NSMakeRange(0, [imageName length]) withTemplate:@""];
98 | if (newImageName) {
99 | [mutablePngFiles replaceObjectAtIndex:index withObject:newImageName];
100 | }
101 | }
102 |
103 | // Remove duplicates and update pngFiles array
104 | imageFiles = [[NSSet setWithArray:mutablePngFiles] allObjects];
105 | }
106 |
107 | // Setup all the retina image firstly
108 | // DISCUSSION: performance vs extensibility. Is a n^2 loop better for extensibility or is a large if statement with better effency
109 | for (NSString *pngPath in _projectImageFiles) {
110 | NSString *imageName = [pngPath lastPathComponent];
111 |
112 | // Does the image have a retina version
113 | for (NSString *retinaRangeString in [self supportedRetinaImagePostfixes]) {
114 | NSRange retinaRange = [imageName rangeOfString:retinaRangeString];
115 | if (retinaRange.location != NSNotFound) {
116 | // Add to retina image paths
117 | [_retinaImagePaths addObject:pngPath];
118 | break;
119 | }
120 | }
121 | }
122 |
123 | dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
124 | dispatch_group_t group = dispatch_group_create();
125 |
126 | // Now loop and check
127 | [imageFiles enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
128 | dispatch_group_async(group, queue, ^{
129 | NSString *imagePath = (NSString *)obj;
130 |
131 | BOOL isImagePathEmpty = [imagePath isEqualToString:@""];
132 | if (!isImagePathEmpty) {
133 |
134 | // Check that it's not a retina image or reserved image name
135 | BOOL isValidImage = [self isValidImageAtPath:imagePath];
136 | if (isValidImage) {
137 | // Grab the file name
138 | NSString *imageName = [imagePath lastPathComponent];
139 |
140 | // Settings items
141 | NSArray *settingsItems = [self searchSettings];
142 | BOOL isSearchCancelled = NO;
143 | for (NSString *extension in settingsItems) {
144 |
145 | // Run the check
146 | if (!isSearchCancelled && [self occurancesOfImageNamed:imageName atDirectory:searchPath inFileExtensionType:extension]) {
147 | isSearchCancelled = YES;
148 | }
149 | }
150 |
151 | // Is it not found - update results
152 | if (!isSearchCancelled)
153 | dispatch_async(dispatch_get_main_queue(), ^{
154 |
155 | if (self.delegate && [self.delegate respondsToSelector:@selector(searcher:didFindUnusedImage:)]) {
156 | [self.delegate searcher:self didFindUnusedImage:imagePath];
157 | }
158 |
159 | });
160 | }
161 | }
162 | });
163 | }];
164 |
165 | dispatch_group_notify(group, queue, ^{
166 | dispatch_async(dispatch_get_main_queue(), ^{
167 |
168 | [_results sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
169 |
170 | if (self.delegate && [self.delegate respondsToSelector:@selector(searcher:didFinishSearch:)]) {
171 | [self.delegate searcher:self didFinishSearch:_results];
172 | }
173 |
174 | isSearching = NO;
175 | [_fileData removeAllObjects];
176 | });
177 | });
178 | }
179 |
180 | - (NSArray *)searchSettings {
181 |
182 | NSMutableArray *settings = [NSMutableArray array];
183 |
184 | if (self.mSearch) {
185 | [settings addObject:@"m"];
186 | }
187 |
188 | if (self.xibSearch) {
189 | [settings addObject:@"xib"];
190 | }
191 |
192 | if (self.storyboardSearch) {
193 | [settings addObject:@"storyboard"];
194 | }
195 |
196 | if (self.cppSearch) {
197 | [settings addObject:@"cpp"];
198 | }
199 |
200 | if (self.headerSearch) {
201 | [settings addObject:@"h"];
202 | }
203 |
204 | if (self.htmlSearch) {
205 | [settings addObject:@"html"];
206 | }
207 |
208 | if (self.mmSearch) {
209 | [settings addObject:@"mm"];
210 | }
211 |
212 | if (self.plistSearch) {
213 | [settings addObject:@"plist"];
214 | }
215 |
216 | if (self.cssSearch) {
217 | [settings addObject:@"css"];
218 | }
219 |
220 | if (self.swiftSearch) {
221 | [settings addObject:@"swift"];
222 | }
223 |
224 | return settings;
225 | }
226 |
227 | - (NSArray *)supportedRetinaImagePostfixes {
228 | return @[@"@2x", @"@3x"];
229 | }
230 |
231 | - (BOOL)isValidImageAtPath:(NSString *)imagePath {
232 | // Grab image name
233 | NSString *imageName = [imagePath lastPathComponent];
234 |
235 | // Check if is retina
236 | for (NSString *retinaRangeString in [self supportedRetinaImagePostfixes]) {
237 | NSRange retinaRange = [imageName rangeOfString:retinaRangeString];
238 | if (retinaRange.location != NSNotFound) {
239 | return NO;
240 | }
241 | }
242 |
243 | // Check for reserved names
244 | BOOL isThirdPartyBundle = [imagePath rangeOfString:@".bundle"].length > 0;
245 | BOOL isNamedDefault = [imageName isEqualToString:@"Default.png"];
246 | BOOL isNamedIcon = [imageName isEqualToString:@"Icon.png"] || [imageName isEqualToString:@"Icon@2x.png"] || [imageName isEqualToString:@"Icon-72.png"];
247 | BOOL isUniversalImage = [imagePath rangeOfString:@"~ipad" options:NSCaseInsensitiveSearch].length > 0;
248 |
249 | return !(isThirdPartyBundle && isNamedDefault && isNamedIcon && isUniversalImage);
250 | }
251 |
252 | - (int)occurancesOfImageNamed:(NSString *)imageName atDirectory:(NSString *)directoryPath inFileExtensionType:(NSString *)extension {
253 | [_fileDataLock lock];
254 |
255 | NSData *data = [_fileData objectForKey:directoryPath];
256 | if (!data) {
257 | NSTask *task = [[NSTask alloc] init];
258 | [task setLaunchPath: @"/bin/sh"];
259 |
260 | // Setup the call
261 | NSString *cmd = [NSString stringWithFormat:@"for filename in `find %@ -name '*.%@'`; do cat $filename 2>/dev/null | grep -o %@ ; done", directoryPath, extension, [imageName stringByDeletingPathExtension]];
262 | NSLog(@"%@", cmd);
263 | NSArray *argvals = [NSArray arrayWithObjects: @"-c", cmd, nil];
264 | [task setArguments: argvals];
265 |
266 | NSPipe *pipe = [NSPipe pipe];
267 | [task setStandardOutput: pipe];
268 | [task launch];
269 |
270 | // Read the response
271 | NSFileHandle *file = [pipe fileHandleForReading];
272 | data = [file readDataToEndOfFile];
273 | NSString *key = [NSString stringWithFormat:@"%@/%@",directoryPath, imageName];
274 |
275 | [_fileData setObject:data forKey:key];
276 | }
277 |
278 | [_fileDataLock unlock];
279 |
280 | NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
281 |
282 | // Calculate the count
283 | NSScanner *scanner = [NSScanner scannerWithString:string];
284 | NSCharacterSet *newline = [NSCharacterSet newlineCharacterSet];
285 | int count = 0;
286 | while ([scanner scanUpToCharactersFromSet:newline intoString:nil]) {
287 | count++;
288 | }
289 |
290 | return count;
291 | }
292 |
293 | @end
294 |
--------------------------------------------------------------------------------
/Unused/Unused.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 1F168D681AAF1CCD0082E1BC /* CONTRIBUTORS in Resources */ = {isa = PBXBuildFile; fileRef = 1F168D671AAF1CCD0082E1BC /* CONTRIBUTORS */; };
11 | 1F55B4A81478097A008A4B0E /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F55B4A71478097A008A4B0E /* Cocoa.framework */; };
12 | 1F55B4B21478097A008A4B0E /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1F55B4B01478097A008A4B0E /* InfoPlist.strings */; };
13 | 1F55B4B51478097A008A4B0E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F55B4B41478097A008A4B0E /* main.m */; };
14 | 1F55B4B81478097A008A4B0E /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 1F55B4B61478097A008A4B0E /* Credits.rtf */; };
15 | 1F55B4BB1478097A008A4B0E /* UnusedAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F55B4BA1478097A008A4B0E /* UnusedAppDelegate.m */; };
16 | 1F55B4BE1478097A008A4B0E /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1F55B4BC1478097A008A4B0E /* MainMenu.xib */; };
17 | 1F6EFD7A147E597400F8950E /* Icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 1F6EFD79147E597400F8950E /* Icon.icns */; };
18 | 1F93632A16D4AC5E00EF0774 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1F93632C16D4AC5E00EF0774 /* Localizable.strings */; };
19 | 1FBF7B301AA8BBAB00EC2E31 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1FBF7B2F1AA8BBAB00EC2E31 /* Images.xcassets */; };
20 | 1FBF7B331AA8BD2800EC2E31 /* FileUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FBF7B321AA8BD2800EC2E31 /* FileUtil.m */; };
21 | 1FBF7B361AAC807500EC2E31 /* Searcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 1FBF7B351AAC807500EC2E31 /* Searcher.m */; };
22 | /* End PBXBuildFile section */
23 |
24 | /* Begin PBXFileReference section */
25 | 1F168D671AAF1CCD0082E1BC /* CONTRIBUTORS */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CONTRIBUTORS; sourceTree = ""; };
26 | 1F55B4A31478097A008A4B0E /* Unused.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Unused.app; sourceTree = BUILT_PRODUCTS_DIR; };
27 | 1F55B4A71478097A008A4B0E /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
28 | 1F55B4AA1478097A008A4B0E /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
29 | 1F55B4AB1478097A008A4B0E /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
30 | 1F55B4AC1478097A008A4B0E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
31 | 1F55B4AF1478097A008A4B0E /* Unused-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Unused-Info.plist"; sourceTree = ""; };
32 | 1F55B4B11478097A008A4B0E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; };
33 | 1F55B4B31478097A008A4B0E /* Unused-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Unused-Prefix.pch"; sourceTree = ""; };
34 | 1F55B4B41478097A008A4B0E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; };
35 | 1F55B4B71478097A008A4B0E /* en */ = {isa = PBXFileReference; lastKnownFileType = wrapper.rtfd; name = en; path = en.lproj/Credits.rtfd; sourceTree = ""; };
36 | 1F55B4B91478097A008A4B0E /* UnusedAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UnusedAppDelegate.h; sourceTree = ""; };
37 | 1F55B4BA1478097A008A4B0E /* UnusedAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UnusedAppDelegate.m; sourceTree = ""; };
38 | 1F55B4BD1478097A008A4B0E /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; };
39 | 1F6EFD79147E597400F8950E /* Icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = Icon.icns; sourceTree = ""; };
40 | 1F93632B16D4AC5E00EF0774 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; };
41 | 1F93632D16D4AC7200EF0774 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = ""; };
42 | 1FBF7B2F1AA8BBAB00EC2E31 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
43 | 1FBF7B311AA8BD2800EC2E31 /* FileUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FileUtil.h; sourceTree = ""; };
44 | 1FBF7B321AA8BD2800EC2E31 /* FileUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FileUtil.m; sourceTree = ""; };
45 | 1FBF7B341AAC807500EC2E31 /* Searcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Searcher.h; sourceTree = ""; };
46 | 1FBF7B351AAC807500EC2E31 /* Searcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Searcher.m; sourceTree = ""; };
47 | /* End PBXFileReference section */
48 |
49 | /* Begin PBXFrameworksBuildPhase section */
50 | 1F55B4A01478097A008A4B0E /* Frameworks */ = {
51 | isa = PBXFrameworksBuildPhase;
52 | buildActionMask = 2147483647;
53 | files = (
54 | 1F55B4A81478097A008A4B0E /* Cocoa.framework in Frameworks */,
55 | );
56 | runOnlyForDeploymentPostprocessing = 0;
57 | };
58 | /* End PBXFrameworksBuildPhase section */
59 |
60 | /* Begin PBXGroup section */
61 | 1F55B4981478097A008A4B0E = {
62 | isa = PBXGroup;
63 | children = (
64 | 1F55B4AD1478097A008A4B0E /* Unused */,
65 | 1F55B4A61478097A008A4B0E /* Frameworks */,
66 | 1F55B4A41478097A008A4B0E /* Products */,
67 | );
68 | sourceTree = "";
69 | };
70 | 1F55B4A41478097A008A4B0E /* Products */ = {
71 | isa = PBXGroup;
72 | children = (
73 | 1F55B4A31478097A008A4B0E /* Unused.app */,
74 | );
75 | name = Products;
76 | sourceTree = "";
77 | };
78 | 1F55B4A61478097A008A4B0E /* Frameworks */ = {
79 | isa = PBXGroup;
80 | children = (
81 | 1F55B4A71478097A008A4B0E /* Cocoa.framework */,
82 | 1F55B4A91478097A008A4B0E /* Other Frameworks */,
83 | );
84 | name = Frameworks;
85 | sourceTree = "";
86 | };
87 | 1F55B4A91478097A008A4B0E /* Other Frameworks */ = {
88 | isa = PBXGroup;
89 | children = (
90 | 1F55B4AA1478097A008A4B0E /* AppKit.framework */,
91 | 1F55B4AB1478097A008A4B0E /* CoreData.framework */,
92 | 1F55B4AC1478097A008A4B0E /* Foundation.framework */,
93 | );
94 | name = "Other Frameworks";
95 | sourceTree = "";
96 | };
97 | 1F55B4AD1478097A008A4B0E /* Unused */ = {
98 | isa = PBXGroup;
99 | children = (
100 | 1F55B4B91478097A008A4B0E /* UnusedAppDelegate.h */,
101 | 1F55B4BA1478097A008A4B0E /* UnusedAppDelegate.m */,
102 | 1FBF7B311AA8BD2800EC2E31 /* FileUtil.h */,
103 | 1FBF7B321AA8BD2800EC2E31 /* FileUtil.m */,
104 | 1FBF7B341AAC807500EC2E31 /* Searcher.h */,
105 | 1FBF7B351AAC807500EC2E31 /* Searcher.m */,
106 | 1F55B4BC1478097A008A4B0E /* MainMenu.xib */,
107 | 1FBF7B2F1AA8BBAB00EC2E31 /* Images.xcassets */,
108 | 1F55B4AE1478097A008A4B0E /* Supporting Files */,
109 | );
110 | path = Unused;
111 | sourceTree = "";
112 | };
113 | 1F55B4AE1478097A008A4B0E /* Supporting Files */ = {
114 | isa = PBXGroup;
115 | children = (
116 | 1F93632C16D4AC5E00EF0774 /* Localizable.strings */,
117 | 1F6EFD79147E597400F8950E /* Icon.icns */,
118 | 1F55B4AF1478097A008A4B0E /* Unused-Info.plist */,
119 | 1F55B4B01478097A008A4B0E /* InfoPlist.strings */,
120 | 1F55B4B31478097A008A4B0E /* Unused-Prefix.pch */,
121 | 1F55B4B41478097A008A4B0E /* main.m */,
122 | 1F55B4B61478097A008A4B0E /* Credits.rtf */,
123 | 1F168D671AAF1CCD0082E1BC /* CONTRIBUTORS */,
124 | );
125 | name = "Supporting Files";
126 | sourceTree = "";
127 | };
128 | /* End PBXGroup section */
129 |
130 | /* Begin PBXNativeTarget section */
131 | 1F55B4A21478097A008A4B0E /* Unused */ = {
132 | isa = PBXNativeTarget;
133 | buildConfigurationList = 1F55B4C11478097A008A4B0E /* Build configuration list for PBXNativeTarget "Unused" */;
134 | buildPhases = (
135 | 1F55B49F1478097A008A4B0E /* Sources */,
136 | 1F55B4A01478097A008A4B0E /* Frameworks */,
137 | 1F55B4A11478097A008A4B0E /* Resources */,
138 | );
139 | buildRules = (
140 | );
141 | dependencies = (
142 | );
143 | name = Unused;
144 | productName = Unused;
145 | productReference = 1F55B4A31478097A008A4B0E /* Unused.app */;
146 | productType = "com.apple.product-type.application";
147 | };
148 | /* End PBXNativeTarget section */
149 |
150 | /* Begin PBXProject section */
151 | 1F55B49A1478097A008A4B0E /* Project object */ = {
152 | isa = PBXProject;
153 | attributes = {
154 | LastUpgradeCheck = 0610;
155 | };
156 | buildConfigurationList = 1F55B49D1478097A008A4B0E /* Build configuration list for PBXProject "Unused" */;
157 | compatibilityVersion = "Xcode 3.2";
158 | developmentRegion = English;
159 | hasScannedForEncodings = 0;
160 | knownRegions = (
161 | en,
162 | fr,
163 | );
164 | mainGroup = 1F55B4981478097A008A4B0E;
165 | productRefGroup = 1F55B4A41478097A008A4B0E /* Products */;
166 | projectDirPath = "";
167 | projectRoot = "";
168 | targets = (
169 | 1F55B4A21478097A008A4B0E /* Unused */,
170 | );
171 | };
172 | /* End PBXProject section */
173 |
174 | /* Begin PBXResourcesBuildPhase section */
175 | 1F55B4A11478097A008A4B0E /* Resources */ = {
176 | isa = PBXResourcesBuildPhase;
177 | buildActionMask = 2147483647;
178 | files = (
179 | 1F168D681AAF1CCD0082E1BC /* CONTRIBUTORS in Resources */,
180 | 1F55B4B21478097A008A4B0E /* InfoPlist.strings in Resources */,
181 | 1F55B4B81478097A008A4B0E /* Credits.rtf in Resources */,
182 | 1F55B4BE1478097A008A4B0E /* MainMenu.xib in Resources */,
183 | 1FBF7B301AA8BBAB00EC2E31 /* Images.xcassets in Resources */,
184 | 1F6EFD7A147E597400F8950E /* Icon.icns in Resources */,
185 | 1F93632A16D4AC5E00EF0774 /* Localizable.strings in Resources */,
186 | );
187 | runOnlyForDeploymentPostprocessing = 0;
188 | };
189 | /* End PBXResourcesBuildPhase section */
190 |
191 | /* Begin PBXSourcesBuildPhase section */
192 | 1F55B49F1478097A008A4B0E /* Sources */ = {
193 | isa = PBXSourcesBuildPhase;
194 | buildActionMask = 2147483647;
195 | files = (
196 | 1FBF7B331AA8BD2800EC2E31 /* FileUtil.m in Sources */,
197 | 1F55B4B51478097A008A4B0E /* main.m in Sources */,
198 | 1FBF7B361AAC807500EC2E31 /* Searcher.m in Sources */,
199 | 1F55B4BB1478097A008A4B0E /* UnusedAppDelegate.m in Sources */,
200 | );
201 | runOnlyForDeploymentPostprocessing = 0;
202 | };
203 | /* End PBXSourcesBuildPhase section */
204 |
205 | /* Begin PBXVariantGroup section */
206 | 1F55B4B01478097A008A4B0E /* InfoPlist.strings */ = {
207 | isa = PBXVariantGroup;
208 | children = (
209 | 1F55B4B11478097A008A4B0E /* en */,
210 | );
211 | name = InfoPlist.strings;
212 | sourceTree = "";
213 | };
214 | 1F55B4B61478097A008A4B0E /* Credits.rtf */ = {
215 | isa = PBXVariantGroup;
216 | children = (
217 | 1F55B4B71478097A008A4B0E /* en */,
218 | );
219 | name = Credits.rtf;
220 | sourceTree = "";
221 | };
222 | 1F55B4BC1478097A008A4B0E /* MainMenu.xib */ = {
223 | isa = PBXVariantGroup;
224 | children = (
225 | 1F55B4BD1478097A008A4B0E /* en */,
226 | );
227 | name = MainMenu.xib;
228 | sourceTree = "";
229 | };
230 | 1F93632C16D4AC5E00EF0774 /* Localizable.strings */ = {
231 | isa = PBXVariantGroup;
232 | children = (
233 | 1F93632B16D4AC5E00EF0774 /* en */,
234 | 1F93632D16D4AC7200EF0774 /* fr */,
235 | );
236 | name = Localizable.strings;
237 | sourceTree = "";
238 | };
239 | /* End PBXVariantGroup section */
240 |
241 | /* Begin XCBuildConfiguration section */
242 | 1F55B4BF1478097A008A4B0E /* Debug */ = {
243 | isa = XCBuildConfiguration;
244 | buildSettings = {
245 | CLANG_WARN_BOOL_CONVERSION = YES;
246 | CLANG_WARN_CONSTANT_CONVERSION = YES;
247 | CLANG_WARN_EMPTY_BODY = YES;
248 | CLANG_WARN_ENUM_CONVERSION = YES;
249 | CLANG_WARN_INT_CONVERSION = YES;
250 | CLANG_WARN_UNREACHABLE_CODE = YES;
251 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
252 | ENABLE_STRICT_OBJC_MSGSEND = YES;
253 | GCC_C_LANGUAGE_STANDARD = gnu99;
254 | GCC_OPTIMIZATION_LEVEL = 0;
255 | GCC_PREPROCESSOR_DEFINITIONS = DEBUG;
256 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
257 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
258 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
259 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
260 | GCC_WARN_UNDECLARED_SELECTOR = YES;
261 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
262 | GCC_WARN_UNUSED_FUNCTION = YES;
263 | GCC_WARN_UNUSED_VARIABLE = YES;
264 | MACOSX_DEPLOYMENT_TARGET = 10.6;
265 | ONLY_ACTIVE_ARCH = YES;
266 | SDKROOT = macosx;
267 | };
268 | name = Debug;
269 | };
270 | 1F55B4C01478097A008A4B0E /* Release */ = {
271 | isa = XCBuildConfiguration;
272 | buildSettings = {
273 | CLANG_WARN_BOOL_CONVERSION = YES;
274 | CLANG_WARN_CONSTANT_CONVERSION = YES;
275 | CLANG_WARN_EMPTY_BODY = YES;
276 | CLANG_WARN_ENUM_CONVERSION = YES;
277 | CLANG_WARN_INT_CONVERSION = YES;
278 | CLANG_WARN_UNREACHABLE_CODE = YES;
279 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
280 | ENABLE_STRICT_OBJC_MSGSEND = YES;
281 | GCC_C_LANGUAGE_STANDARD = gnu99;
282 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
283 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
284 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
285 | GCC_WARN_UNDECLARED_SELECTOR = YES;
286 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
287 | GCC_WARN_UNUSED_FUNCTION = YES;
288 | GCC_WARN_UNUSED_VARIABLE = YES;
289 | MACOSX_DEPLOYMENT_TARGET = 10.6;
290 | SDKROOT = macosx;
291 | };
292 | name = Release;
293 | };
294 | 1F55B4C21478097A008A4B0E /* Debug */ = {
295 | isa = XCBuildConfiguration;
296 | buildSettings = {
297 | ALWAYS_SEARCH_USER_PATHS = NO;
298 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
299 | CLANG_ENABLE_OBJC_ARC = YES;
300 | CODE_SIGN_IDENTITY = "";
301 | COMBINE_HIDPI_IMAGES = YES;
302 | COPY_PHASE_STRIP = NO;
303 | GCC_DYNAMIC_NO_PIC = NO;
304 | GCC_ENABLE_OBJC_EXCEPTIONS = YES;
305 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
306 | GCC_PREFIX_HEADER = "Unused/Unused-Prefix.pch";
307 | INFOPLIST_FILE = "Unused/Unused-Info.plist";
308 | PRODUCT_NAME = "$(TARGET_NAME)";
309 | WRAPPER_EXTENSION = app;
310 | };
311 | name = Debug;
312 | };
313 | 1F55B4C31478097A008A4B0E /* Release */ = {
314 | isa = XCBuildConfiguration;
315 | buildSettings = {
316 | ALWAYS_SEARCH_USER_PATHS = NO;
317 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
318 | CLANG_ENABLE_OBJC_ARC = YES;
319 | CODE_SIGN_IDENTITY = "3rd Party Mac Developer Application: Seamonster Ltd.";
320 | COMBINE_HIDPI_IMAGES = YES;
321 | COPY_PHASE_STRIP = YES;
322 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
323 | GCC_ENABLE_OBJC_EXCEPTIONS = YES;
324 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
325 | GCC_PREFIX_HEADER = "Unused/Unused-Prefix.pch";
326 | INFOPLIST_FILE = "Unused/Unused-Info.plist";
327 | PRODUCT_NAME = "$(TARGET_NAME)";
328 | WRAPPER_EXTENSION = app;
329 | };
330 | name = Release;
331 | };
332 | 1F9DF8EF1487E47A00A1EAC8 /* Distribution */ = {
333 | isa = XCBuildConfiguration;
334 | buildSettings = {
335 | CLANG_WARN_BOOL_CONVERSION = YES;
336 | CLANG_WARN_CONSTANT_CONVERSION = YES;
337 | CLANG_WARN_EMPTY_BODY = YES;
338 | CLANG_WARN_ENUM_CONVERSION = YES;
339 | CLANG_WARN_INT_CONVERSION = YES;
340 | CLANG_WARN_UNREACHABLE_CODE = YES;
341 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
342 | ENABLE_STRICT_OBJC_MSGSEND = YES;
343 | GCC_C_LANGUAGE_STANDARD = gnu99;
344 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
345 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
346 | GCC_WARN_ABOUT_RETURN_TYPE = YES;
347 | GCC_WARN_UNDECLARED_SELECTOR = YES;
348 | GCC_WARN_UNINITIALIZED_AUTOS = YES;
349 | GCC_WARN_UNUSED_FUNCTION = YES;
350 | GCC_WARN_UNUSED_VARIABLE = YES;
351 | MACOSX_DEPLOYMENT_TARGET = 10.6;
352 | SDKROOT = macosx;
353 | };
354 | name = Distribution;
355 | };
356 | 1F9DF8F01487E47A00A1EAC8 /* Distribution */ = {
357 | isa = XCBuildConfiguration;
358 | buildSettings = {
359 | ALWAYS_SEARCH_USER_PATHS = NO;
360 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
361 | CLANG_ENABLE_OBJC_ARC = YES;
362 | CODE_SIGN_IDENTITY = "3rd Party Mac Developer Application: Seamonster Ltd.";
363 | COMBINE_HIDPI_IMAGES = YES;
364 | COPY_PHASE_STRIP = YES;
365 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
366 | GCC_ENABLE_OBJC_EXCEPTIONS = YES;
367 | GCC_PRECOMPILE_PREFIX_HEADER = YES;
368 | GCC_PREFIX_HEADER = "Unused/Unused-Prefix.pch";
369 | INFOPLIST_FILE = "Unused/Unused-Info.plist";
370 | PRODUCT_NAME = "$(TARGET_NAME)";
371 | PROVISIONING_PROFILE = "7B15303B-2950-41B3-8360-420802231324";
372 | WRAPPER_EXTENSION = app;
373 | };
374 | name = Distribution;
375 | };
376 | /* End XCBuildConfiguration section */
377 |
378 | /* Begin XCConfigurationList section */
379 | 1F55B49D1478097A008A4B0E /* Build configuration list for PBXProject "Unused" */ = {
380 | isa = XCConfigurationList;
381 | buildConfigurations = (
382 | 1F55B4BF1478097A008A4B0E /* Debug */,
383 | 1F55B4C01478097A008A4B0E /* Release */,
384 | 1F9DF8EF1487E47A00A1EAC8 /* Distribution */,
385 | );
386 | defaultConfigurationIsVisible = 0;
387 | defaultConfigurationName = Release;
388 | };
389 | 1F55B4C11478097A008A4B0E /* Build configuration list for PBXNativeTarget "Unused" */ = {
390 | isa = XCConfigurationList;
391 | buildConfigurations = (
392 | 1F55B4C21478097A008A4B0E /* Debug */,
393 | 1F55B4C31478097A008A4B0E /* Release */,
394 | 1F9DF8F01487E47A00A1EAC8 /* Distribution */,
395 | );
396 | defaultConfigurationIsVisible = 0;
397 | defaultConfigurationName = Release;
398 | };
399 | /* End XCConfigurationList section */
400 | };
401 | rootObject = 1F55B49A1478097A008A4B0E /* Project object */;
402 | }
403 |
--------------------------------------------------------------------------------
/Unused/Unused/en.lproj/MainMenu.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
650 |
651 |
652 |
653 |
654 |
655 |
656 |
657 |
658 |
659 |
660 |
661 |
662 |
663 |
664 |
665 |
666 |
667 |
668 |
669 |
670 |
671 |
672 |
673 |
674 |
675 |
676 |
677 |
678 |
679 |
680 |
681 |
682 |
683 |
684 |
685 |
686 |
687 |
688 |
689 |
690 |
691 |
692 |
693 |
694 |
695 |
696 |
697 |
698 |
699 |
700 |
701 |
702 |
703 |
704 |
705 |
706 |
707 |
708 |
709 |
710 |
711 |
712 |
713 |
714 |
715 |
716 |
717 |
718 |
719 |
720 |
721 |
722 |
723 |
724 |
725 |
726 |
727 |
728 |
729 |
730 |
731 |
739 |
747 |
755 |
763 |
771 |
779 |
787 |
795 |
803 |
814 |
825 |
826 |
827 |
828 |
829 |
830 |
831 |
832 |
833 |
834 |
835 |
836 |
837 |
838 |
839 |
840 |
841 |
842 |
843 |
844 |
845 |
846 |
847 |
848 |
849 |
850 |
851 |
852 |
853 |
854 |
855 |
856 |
857 |
858 |
859 |
860 |
861 |
862 |
863 |
864 |
865 |
866 |
867 |
868 |
869 |
870 |
871 |
872 |
873 |
874 |
875 |
876 |
877 |
878 |
879 |
880 |
881 |
882 |
883 |
884 |
885 |
886 |
887 |
888 |
889 |
890 |
891 |
892 |
903 |
904 |
905 |
906 |
907 |
908 |
909 |
910 |
911 |
912 |
913 |
914 |
915 |
916 |
917 |
918 |
919 |
920 |
921 |
922 |
923 |
924 |
932 |
933 |
934 |
935 |
936 |
937 |
938 |
939 |
940 |
941 |
949 |
950 |
951 |
952 |
953 |
954 |
955 |
956 |
957 |
958 |
959 |
960 |
961 |
962 |
963 |
964 |
965 |
966 |
967 |
968 |
969 |
970 |
971 |
972 |
973 |
974 |
975 |
976 |
977 |
978 |
979 |
--------------------------------------------------------------------------------