@@ -83,7 +83,31 @@ - (void)parseImageSetAtURL:(NSURL *)url;
83
83
if (!contents) {
84
84
return ;
85
85
}
86
-
86
+
87
+ // Sort the variants: retina4 comes first, then iphone/ipad-specific, then universal
88
+ // Within each group, 2x comes before 1x
89
+ NSArray *variants = [contents[@" images" ]sortedArrayUsingComparator: ^NSComparisonResult (id obj1,id obj2) {
90
+ if (![obj1[@" subtype" ]isEqualToString: obj2[@" subtype" ]]) {
91
+ if (obj1[@" subtype" ]) {
92
+ return NSOrderedAscending;
93
+ }
94
+ if (obj2[@" subtype" ]) {
95
+ return NSOrderedDescending;
96
+ }
97
+ }
98
+
99
+ if (![obj1[@" idiom" ]isEqualToString: obj2[@" idiom" ]]) {
100
+ if ([obj1[@" idiom" ]isEqualToString: @" universal" ]) {
101
+ return NSOrderedDescending;
102
+ }
103
+ if ([obj2[@" idiom" ]isEqualToString: @" universal" ]) {
104
+ return NSOrderedAscending;
105
+ }
106
+ }
107
+
108
+ return -[obj1[@" scale" ]compare: obj2[@" scale" ]];
109
+ }];
110
+
87
111
NSString *interface = [NSString stringWithFormat: @" + (UIImage *)imageFor%@ ;\n " , name];
88
112
@synchronized (self.interfaceContents ) {
89
113
[self .interfaceContentsaddObject: interface];
@@ -92,47 +116,68 @@ - (void)parseImageSetAtURL:(NSURL *)url;
92
116
NSMutableString *implementation = [interfacemutableCopy ];
93
117
[implementationappendString: @" {\n " ];
94
118
95
- [implementationappendFormat: @" UIImage *cachedImage = [[self imageCache] objectForKey:@\" %@ \" ];\n " , name];
96
- [implementationappendString: @" if (cachedImage) {\n " ];
97
- [implementationappendString: @" return cachedImage;\n " ];
98
- [implementationappendString: @" }\n\n " ];
99
-
100
- for (NSDictionary *variant in contents[@" images" ]) {
101
- BOOL isUniversal = [variant[@" idiom" ]isEqualToString: @" universal" ];
102
- NSString *indentation =@" " ;
103
- if (!isUniversal) {
104
- NSString *idiom = [variant[@" idiom" ]isEqualToString: @" iphone" ] ?@" UIUserInterfaceIdiomPhone" :@" UIUserInterfaceIdiomPad" ;
105
- [implementationappendFormat: @" if (UI_USER_INTERFACE_IDIOM() ==%@ ) {\n " , idiom];
106
- indentation =@" " ;
119
+ // If there are only one or two variants and they only differ by 1x or 2x and they're not resizable, short circuit
120
+ BOOL shortCircuit = (variants.count ==1 );
121
+ if (variants.count ==2 ) {
122
+ if (!variants[0 ][@" resizing" ] && !variants[1 ][@" resizing" ]) {
123
+ NSString *filename1 = [variants[0 ][@" filename" ]stringByReplacingOccurrencesOfString: @" @2x" withString: @" " ];
124
+ NSString *filename2 = [variants[1 ][@" filename" ]stringByReplacingOccurrencesOfString: @" @2x" withString: @" " ];
125
+ shortCircuit = [filename1isEqualToString: filename2];
107
126
}
127
+ }
128
+ if (shortCircuit) {
129
+ [implementationappendFormat: @" return [UIImage imageNamed:@\" %@ \" ];\n " , [variantslastObject ][@" filename" ]];
130
+ [implementationappendString: @" }\n " ];
131
+
132
+ }else {
133
+ [implementationappendFormat: @" UIImage *image = [[self imageCache] objectForKey:@\" %@ \" ];\n " , name];
134
+ [implementationappendString: @" if (image) {\n " ];
135
+ [implementationappendString: @" return image;\n " ];
136
+ [implementationappendString: @" }\n\n " ];
108
137
109
- CGFloat scale = [variant[@" scale" ]floatValue ];
110
- NSString *filename = [variant[@" filename" ]stringByReplacingOccurrencesOfString: [NSString stringWithFormat: @" @%@ " , variant[@" scale" ]]withString: @" " ];
111
- [implementationappendFormat: @" %@ if ([UIScreen mainScreen].scale ==%.1f f) {\n " , indentation, scale];
112
- [implementationappendFormat: @" %@ UIImage *baseImage = [UIImage imageNamed:@\" %@ \" ];\n " , indentation, filename];
113
-
114
- NSDictionary *resizing = variant[@" resizing" ];
115
- if (resizing) {
116
- CGFloat top = [resizing[@" capInsets" ][@" top" ]floatValue ] / scale;
117
- CGFloat left = [resizing[@" capInsets" ][@" left" ]floatValue ] / scale;
118
- CGFloat bottom = [resizing[@" capInsets" ][@" bottom" ]floatValue ] / scale;
119
- CGFloat right = [resizing[@" capInsets" ][@" right" ]floatValue ] / scale;
120
- NSString *mode = [resizing[@" center" ][@" mode" ]isEqualToString: @" stretch" ] ?@" UIImageResizingModeStretch" :@" UIImageResizingModeTile" ;
138
+ for (NSDictionary *variant in variants) {
139
+ if (!variant[@" filename" ]) {
140
+ continue ;
141
+ }
142
+ BOOL isUniversal = [variant[@" idiom" ]isEqualToString: @" universal" ];
143
+ NSString *indentation =@" " ;
144
+ if (!isUniversal) {
145
+ NSString *idiom = [variant[@" idiom" ]isEqualToString: @" iphone" ] ?@" UIUserInterfaceIdiomPhone" :@" UIUserInterfaceIdiomPad" ;
146
+ [implementationappendFormat: @" if (UI_USER_INTERFACE_IDIOM() ==%@ ) {\n " , idiom];
147
+ indentation =@" " ;
148
+ }
149
+
150
+ CGFloat scale = [variant[@" scale" ]floatValue ];
151
+ NSString *filename = [variant[@" filename" ]stringByReplacingOccurrencesOfString: [NSString stringWithFormat: @" @%@ " , variant[@" scale" ]]withString: @" " ];
152
+ NSString *scaleIndentation = [indentationstringByAppendingString: @" " ];
153
+ [implementationappendFormat: @" %@ if ([UIScreen mainScreen].scale ==%.1f f) {\n " , scaleIndentation, scale];
154
+ [implementationappendFormat: @" %@ image = [UIImage imageNamed:@\" %@ \" ];\n " , scaleIndentation, filename];
155
+
156
+ NSDictionary *resizing = variant[@" resizing" ];
157
+ if (resizing) {
158
+ CGFloat top = [resizing[@" capInsets" ][@" top" ]floatValue ] / scale;
159
+ CGFloat left = [resizing[@" capInsets" ][@" left" ]floatValue ] / scale;
160
+ CGFloat bottom = [resizing[@" capInsets" ][@" bottom" ]floatValue ] / scale;
161
+ CGFloat right = [resizing[@" capInsets" ][@" right" ]floatValue ] / scale;
162
+ NSString *mode = [resizing[@" center" ][@" mode" ]isEqualToString: @" stretch" ] ?@" UIImageResizingModeStretch" :@" UIImageResizingModeTile" ;
163
+
164
+ [implementationappendFormat: @" %@ image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(%.1f f,%.1f f,%.1f f,%.1f f) resizingMode:%@ ];\n " , scaleIndentation, top, left, bottom, right, mode];
165
+ }
121
166
122
- [implementationappendFormat: @" %@ return [baseImage resizableImageWithCapInsets:UIEdgeInsetsMake(%.1f f,%.1f f,%.1f f,%.1f f) resizingMode:%@ ];\n " , indentation, top, left, bottom, right, mode];
123
- }else {
124
- [implementationappendFormat: @" %@ return baseImage;\n " , indentation];
167
+ [implementationappendFormat: @" %@ }\n " , scaleIndentation];
168
+
169
+ if (!isUniversal) {
170
+ [implementationappendFormat: @" %@ }\n " , indentation];
171
+ }
172
+
173
+ [implementationappendString: @" \n " ];
125
174
}
126
-
127
- [implementationappendFormat: @" %@ }\n " , indentation];
128
175
129
- if (!isUniversal) {
130
- [implementationappendString: @" } \n " ];
131
- }
176
+ [implementation appendFormat: @" [[self imageCache] setObject:image forKey:@ \" %@ \" ]; \n " , name];
177
+ [implementationappendString: @" return image; \n " ];
178
+ [implementation appendString: @" } \n " ];
132
179
}
133
180
134
- [implementationappendString: @" return nil;\n " ];
135
- [implementationappendString: @" }\n " ];
136
181
@synchronized (self.implementationContents ) {
137
182
[self .implementationContentsaddObject: implementation];
138
183
}