├── GusUtilsTests ├── en.lproj │ └── InfoPlist.strings ├── GusUtilsTests-Prefix.pch ├── GusUtilsTests.h ├── GusUtilsTests.m └── GusUtilsTests-Info.plist ├── .gitignore ├── GusUtils ├── GusUtils-Prefix.pch ├── NSMutableDictionary+ImageMetadata.h └── NSMutableDictionary+ImageMetadata.m ├── GusUtils.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata ├── xcuserdata │ └── gustavo.xcuserdatad │ │ └── xcschemes │ │ ├── xcschememanagement.plist │ │ └── GusUtils.xcscheme └── project.pbxproj ├── README.markdown └── LICENSE /GusUtilsTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.DS_Store 2 | /GusUtils.xcodeproj/project.xcworkspace/xcuserdata/gustavo.xcuserdatad/UserInterfaceState.xcuserstate 3 | /GusUtils/.DS_Store 4 | GusUtils.xcodeproj/xcuserdata/ 5 | -------------------------------------------------------------------------------- /GusUtils/GusUtils-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'GusUtils' target in the 'GusUtils' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /GusUtilsTests/GusUtilsTests-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'GusUtilsTests' target in the 'GusUtilsTests' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /GusUtils.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /GusUtilsTests/GusUtilsTests.h: -------------------------------------------------------------------------------- 1 | // 2 | // GusUtilsTests.h 3 | // GusUtilsTests 4 | // 5 | // Created by Gustavo Ambrozio on 9/5/11. 6 | // Copyright 2011 CodeCrop Software. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface GusUtilsTests : SenTestCase { 13 | @private 14 | 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /GusUtilsTests/GusUtilsTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // GusUtilsTests.m 3 | // GusUtilsTests 4 | // 5 | // Created by Gustavo Ambrozio on 9/5/11. 6 | // Copyright 2011 CodeCrop Software. All rights reserved. 7 | // 8 | 9 | #import "GusUtilsTests.h" 10 | 11 | 12 | @implementation GusUtilsTests 13 | 14 | - (void)setUp 15 | { 16 | [super setUp]; 17 | 18 | // Set-up code here. 19 | } 20 | 21 | - (void)tearDown 22 | { 23 | // Tear-down code here. 24 | 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample 29 | { 30 | STFail(@"Unit tests are not implemented yet in GusUtilsTests"); 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /GusUtils.xcodeproj/xcuserdata/gustavo.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | GusUtils.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | EC50914C1378582800BCF230 16 | 17 | primary 18 | 19 | 20 | EC5091591378582800BCF230 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /GusUtilsTests/GusUtilsTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | This is a collections of helpfull classes and categories that I use for iOS development that I'm making available so that everyone can use and improve. 4 | 5 | Most of the stuff I'll include will have a blog post associated with it. 6 | 7 | * NSMUtableDictionary+ImageMetadata: Used to make it easy to add metadata (including geolocation) to images in iOS: http://blog.codecropper.com/2011/05/adding-metadata-to-ios-images-the-easy-way/ and http://blog.codecropper.com/2011/05/getting-metadata-from-images-on-ios 8 | 9 | 10 | # License 11 | 12 | This library is licensed under the MIT license. See the LICENSE file. If you want to use but can't give attribution send me an email and I'll probably be OK with it as long as you're not creating a doomsday machine. 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2011 by Gustavo Pelosi Ambrozio 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /GusUtils/NSMutableDictionary+ImageMetadata.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableDictionary+ImageMetadata.h 3 | // 4 | // Created by Gustavo Ambrozio on 28/2/11. 5 | // 6 | 7 | #import 8 | #import 9 | #import 10 | #import 11 | 12 | @interface NSMutableDictionary (ImageMetadataCategory) 13 | 14 | - (id)initWithImageSampleBuffer:(CMSampleBufferRef) imageDataSampleBuffer; 15 | 16 | /* 17 | Be careful with this method: because it uses blocks, there's no guarantee that your 18 | imageMetadata dictionary will be populated when this code runs. In some testing I've 19 | done it sometimes runs the code inside the block even before the [library autorelease] 20 | is executed. But the first time you run this, the code inside the block will only run 21 | on another cycle of the apps main loop. So, if you need to use this info right away, 22 | it's better to schedule a method on the run queue for later with: 23 | 24 | [self performSelectorOnMainThread: withObject: waitUntilDone:NO]; 25 | */ 26 | - (id)initWithInfoFromImagePicker:(NSDictionary *)info; 27 | 28 | /* 29 | Be careful with this method: because it uses blocks, there's no guarantee that your 30 | imageMetadata dictionary will be populated when this code runs. In some testing I've 31 | done it sometimes runs the code inside the block even before the [library autorelease] 32 | is executed. But the first time you run this, the code inside the block will only run 33 | on another cycle of the apps main loop. So, if you need to use this info right away, 34 | it's better to schedule a method on the run queue for later with: 35 | 36 | [self performSelectorOnMainThread: withObject: waitUntilDone:NO]; 37 | */ 38 | - (id)initFromAssetURL:(NSURL*)assetURL; 39 | 40 | - (void)setUserComment:(NSString*)comment; 41 | - (void)setDateOriginal:(NSDate *)date; 42 | - (void)setDateDigitized:(NSDate *)date; 43 | - (void)setMake:(NSString*)make model:(NSString*)model software:(NSString*)software; 44 | - (void)setDescription:(NSString*)description; 45 | - (void)setKeywords:(NSString*)keywords; 46 | - (void)setImageOrientation:(UIImageOrientation)orientation; 47 | - (void)setDigitalZoom:(CGFloat)zoom; 48 | - (void)setHeading:(CLHeading*)heading; 49 | 50 | @property (nonatomic, retain) CLLocation *location; 51 | @property (nonatomic, assign) CLLocationDirection trueHeading; 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /GusUtils.xcodeproj/xcuserdata/gustavo.xcuserdatad/xcschemes/GusUtils.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 14 | 20 | 21 | 22 | 23 | 24 | 29 | 30 | 32 | 38 | 39 | 40 | 41 | 42 | 50 | 51 | 52 | 53 | 60 | 61 | 63 | 64 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /GusUtils/NSMutableDictionary+ImageMetadata.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSMutableDictionary+ImageMetadata.m 3 | // 4 | // Created by Gustavo Ambrozio on 28/2/11. 5 | // 6 | 7 | #import "NSMutableDictionary+ImageMetadata.h" 8 | #import 9 | #import 10 | 11 | @implementation NSMutableDictionary (ImageMetadataCategory) 12 | 13 | @dynamic location; 14 | 15 | - (NSString *)getUTCFormattedDate:(NSDate *)localDate { 16 | static NSDateFormatter *dateFormatter = nil; 17 | if (dateFormatter == nil) { 18 | dateFormatter = [[NSDateFormatter alloc] init]; 19 | [dateFormatter setDateFormat:@"yyyy:MM:dd HH:mm:ss"]; 20 | } 21 | NSString *dateString = [dateFormatter stringFromDate:localDate]; 22 | return dateString; 23 | } 24 | 25 | - (id)initWithImageSampleBuffer:(CMSampleBufferRef) imageDataSampleBuffer { 26 | 27 | // Dictionary of metadata is here 28 | CFDictionaryRef metadataDict = CMCopyDictionaryOfAttachments(NULL, imageDataSampleBuffer, kCMAttachmentMode_ShouldPropagate); 29 | 30 | // Just init with it.... 31 | self = [self initWithDictionary:(NSDictionary*)metadataDict]; 32 | 33 | // Release it 34 | CFRelease(metadataDict); 35 | return self; 36 | } 37 | 38 | - (id)initWithInfoFromImagePicker:(NSDictionary *)info { 39 | 40 | if ((self = [self init])) { 41 | 42 | // Key UIImagePickerControllerReferenceURL only exists in iOS 4.1 43 | if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 4.1f) { 44 | 45 | NSURL* assetURL = nil; 46 | if ((assetURL = [info objectForKey:UIImagePickerControllerReferenceURL])) { 47 | 48 | ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; 49 | [library assetForURL:assetURL 50 | resultBlock:^(ALAsset *asset) { 51 | NSDictionary *metadata = asset.defaultRepresentation.metadata; 52 | [self addEntriesFromDictionary:metadata]; 53 | } 54 | failureBlock:^(NSError *error) { 55 | }]; 56 | [library autorelease]; 57 | } 58 | else { 59 | NSDictionary *metadata = [info objectForKey:UIImagePickerControllerMediaMetadata]; 60 | if (metadata) 61 | [self addEntriesFromDictionary:metadata]; 62 | } 63 | } 64 | } 65 | 66 | return self; 67 | } 68 | 69 | - (id)initFromAssetURL:(NSURL*)assetURL { 70 | 71 | if ((self = [self init])) { 72 | ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; 73 | [library assetForURL:assetURL 74 | resultBlock:^(ALAsset *asset) { 75 | NSDictionary *metadata = asset.defaultRepresentation.metadata; 76 | [self addEntriesFromDictionary:metadata]; 77 | } 78 | failureBlock:^(NSError *error) { 79 | }]; 80 | [library autorelease]; 81 | } 82 | 83 | return self; 84 | } 85 | 86 | // Mostly from here: http://stackoverflow.com/questions/3884060/need-help-in-saving-geotag-info-with-photo-on-ios4-1 87 | - (void)setLocation:(CLLocation *)location { 88 | 89 | if (location) { 90 | 91 | CLLocationDegrees exifLatitude = location.coordinate.latitude; 92 | CLLocationDegrees exifLongitude = location.coordinate.longitude; 93 | 94 | NSString *latRef; 95 | NSString *lngRef; 96 | if (exifLatitude < 0.0) { 97 | exifLatitude = exifLatitude * -1.0f; 98 | latRef = @"S"; 99 | } else { 100 | latRef = @"N"; 101 | } 102 | 103 | if (exifLongitude < 0.0) { 104 | exifLongitude = exifLongitude * -1.0f; 105 | lngRef = @"W"; 106 | } else { 107 | lngRef = @"E"; 108 | } 109 | 110 | NSMutableDictionary *locDict = [[NSMutableDictionary alloc] init]; 111 | if ([self objectForKey:(NSString*)kCGImagePropertyGPSDictionary]) { 112 | [locDict addEntriesFromDictionary:[self objectForKey:(NSString*)kCGImagePropertyGPSDictionary]]; 113 | } 114 | [locDict setObject:[self getUTCFormattedDate:location.timestamp] forKey:(NSString*)kCGImagePropertyGPSTimeStamp]; 115 | [locDict setObject:latRef forKey:(NSString*)kCGImagePropertyGPSLatitudeRef]; 116 | [locDict setObject:[NSNumber numberWithFloat:exifLatitude] forKey:(NSString*)kCGImagePropertyGPSLatitude]; 117 | [locDict setObject:lngRef forKey:(NSString*)kCGImagePropertyGPSLongitudeRef]; 118 | [locDict setObject:[NSNumber numberWithFloat:exifLongitude] forKey:(NSString*)kCGImagePropertyGPSLongitude]; 119 | [locDict setObject:[NSNumber numberWithFloat:location.horizontalAccuracy] forKey:(NSString*)kCGImagePropertyGPSDOP]; 120 | [locDict setObject:[NSNumber numberWithFloat:location.altitude] forKey:(NSString*)kCGImagePropertyGPSAltitude]; 121 | 122 | [self setObject:locDict forKey:(NSString*)kCGImagePropertyGPSDictionary]; 123 | [locDict release]; 124 | } 125 | } 126 | 127 | // Set heading while preserving location metadata, if it exists. 128 | - (void)setHeading:(CLHeading *)locationHeading { 129 | 130 | if (locationHeading) { 131 | [self setTrueHeading:locationHeading.trueHeading]; 132 | } 133 | } 134 | 135 | - (void)setTrueHeading:(CLLocationDirection)trueHeading { 136 | NSMutableDictionary *locDict = [[NSMutableDictionary alloc] init]; 137 | if ([self objectForKey:(NSString*)kCGImagePropertyGPSDictionary]) { 138 | [locDict addEntriesFromDictionary:[self objectForKey:(NSString*)kCGImagePropertyGPSDictionary]]; 139 | } 140 | [locDict setObject:@"T" forKey:(NSString*)kCGImagePropertyGPSImgDirectionRef]; 141 | [locDict setObject:[NSNumber numberWithFloat:trueHeading] forKey:(NSString*)kCGImagePropertyGPSImgDirection]; 142 | 143 | [self setObject:locDict forKey:(NSString*)kCGImagePropertyGPSDictionary]; 144 | [locDict release]; 145 | } 146 | 147 | - (CLLocation*)location { 148 | NSDictionary *locDict = [self objectForKey:(NSString*)kCGImagePropertyGPSDictionary]; 149 | if (locDict) { 150 | 151 | CLLocationDegrees lat = [[locDict objectForKey:(NSString*)kCGImagePropertyGPSLatitude] floatValue]; 152 | CLLocationDegrees lng = [[locDict objectForKey:(NSString*)kCGImagePropertyGPSLongitude] floatValue]; 153 | NSString *latRef = [locDict objectForKey:(NSString*)kCGImagePropertyGPSLatitudeRef]; 154 | NSString *lngRef = [locDict objectForKey:(NSString*)kCGImagePropertyGPSLongitudeRef]; 155 | 156 | if ([@"S" isEqualToString:latRef]) 157 | lat *= -1.0f; 158 | if ([@"W" isEqualToString:lngRef]) 159 | lng *= -1.0f; 160 | 161 | CLLocation *location = [[[CLLocation alloc] initWithLatitude:lat longitude:lng] autorelease]; 162 | return location; 163 | } 164 | 165 | return nil; 166 | } 167 | 168 | - (CLLocationDirection)trueHeading { 169 | NSDictionary *locDict = [self objectForKey:(NSString*)kCGImagePropertyGPSDictionary]; 170 | CLLocationDirection heading = 0; 171 | if (locDict) { 172 | heading = [[locDict objectForKey:(NSString*)kCGImagePropertyGPSImgDirection] doubleValue]; 173 | } 174 | 175 | return heading; 176 | } 177 | 178 | - (NSMutableDictionary *)dictionaryForKey:(CFStringRef)key { 179 | NSDictionary *dict = [self objectForKey:(NSString*)key]; 180 | NSMutableDictionary *mutableDict; 181 | 182 | if (dict == nil) { 183 | mutableDict = [NSMutableDictionary dictionaryWithCapacity:1]; 184 | [self setObject:mutableDict forKey:(NSString*)key]; 185 | } else { 186 | if ([dict isMemberOfClass:[NSMutableDictionary class]]) 187 | { 188 | mutableDict = (NSMutableDictionary*)dict; 189 | } else { 190 | mutableDict = [[dict mutableCopy] autorelease]; 191 | [self setObject:mutableDict forKey:(NSString*)key]; 192 | } 193 | } 194 | 195 | return mutableDict; 196 | } 197 | 198 | 199 | #define EXIF_DICT [self dictionaryForKey:kCGImagePropertyExifDictionary] 200 | #define TIFF_DICT [self dictionaryForKey:kCGImagePropertyTIFFDictionary] 201 | #define IPTC_DICT [self dictionaryForKey:kCGImagePropertyIPTCDictionary] 202 | 203 | 204 | - (void)setUserComment:(NSString*)comment { 205 | [EXIF_DICT setObject:comment forKey:(NSString*)kCGImagePropertyExifUserComment]; 206 | } 207 | 208 | - (void)setDateOriginal:(NSDate *)date { 209 | NSString *dateString = [self getUTCFormattedDate:date]; 210 | [EXIF_DICT setObject:dateString forKey:(NSString*)kCGImagePropertyExifDateTimeOriginal]; 211 | [TIFF_DICT setObject:dateString forKey:(NSString*)kCGImagePropertyTIFFDateTime]; 212 | } 213 | 214 | - (void)setDateDigitized:(NSDate *)date { 215 | NSString *dateString = [self getUTCFormattedDate:date]; 216 | [EXIF_DICT setObject:dateString forKey:(NSString*)kCGImagePropertyExifDateTimeDigitized]; 217 | } 218 | 219 | - (void)setMake:(NSString*)make model:(NSString*)model software:(NSString*)software { 220 | NSMutableDictionary *tiffDict = TIFF_DICT; 221 | [tiffDict setObject:make forKey:(NSString*)kCGImagePropertyTIFFMake]; 222 | [tiffDict setObject:model forKey:(NSString*)kCGImagePropertyTIFFModel]; 223 | [tiffDict setObject:software forKey:(NSString*)kCGImagePropertyTIFFSoftware]; 224 | } 225 | 226 | - (void)setDescription:(NSString*)description { 227 | [TIFF_DICT setObject:description forKey:(NSString*)kCGImagePropertyTIFFImageDescription]; 228 | } 229 | 230 | - (void)setKeywords:(NSString*)keywords { 231 | [IPTC_DICT setObject:keywords forKey:(NSString*)kCGImagePropertyIPTCKeywords]; 232 | } 233 | 234 | - (void)setDigitalZoom:(CGFloat)zoom { 235 | [EXIF_DICT setObject:[NSNumber numberWithFloat:zoom] forKey:(NSString*)kCGImagePropertyExifDigitalZoomRatio]; 236 | } 237 | 238 | 239 | /* The intended display orientation of the image. If present, the value 240 | * of this key is a CFNumberRef with the same value as defined by the 241 | * TIFF and Exif specifications. That is: 242 | * 1 = 0th row is at the top, and 0th column is on the left. 243 | * 2 = 0th row is at the top, and 0th column is on the right. 244 | * 3 = 0th row is at the bottom, and 0th column is on the right. 245 | * 4 = 0th row is at the bottom, and 0th column is on the left. 246 | * 5 = 0th row is on the left, and 0th column is the top. 247 | * 6 = 0th row is on the right, and 0th column is the top. 248 | * 7 = 0th row is on the right, and 0th column is the bottom. 249 | * 8 = 0th row is on the left, and 0th column is the bottom. 250 | * If not present, a value of 1 is assumed. */ 251 | 252 | // Reference: http://sylvana.net/jpegcrop/exif_orientation.html 253 | - (void)setImageOrientation:(UIImageOrientation)orientation { 254 | int o = 1; 255 | switch (orientation) { 256 | case UIImageOrientationUp: 257 | o = 1; 258 | break; 259 | 260 | case UIImageOrientationDown: 261 | o = 3; 262 | break; 263 | 264 | case UIImageOrientationLeft: 265 | o = 8; 266 | break; 267 | 268 | case UIImageOrientationRight: 269 | o = 6; 270 | break; 271 | 272 | case UIImageOrientationUpMirrored: 273 | o = 2; 274 | break; 275 | 276 | case UIImageOrientationDownMirrored: 277 | o = 4; 278 | break; 279 | 280 | case UIImageOrientationLeftMirrored: 281 | o = 5; 282 | break; 283 | 284 | case UIImageOrientationRightMirrored: 285 | o = 7; 286 | break; 287 | } 288 | 289 | [self setObject:[NSNumber numberWithInt:o] forKey:(NSString*)kCGImagePropertyOrientation]; 290 | } 291 | 292 | 293 | 294 | @end 295 | -------------------------------------------------------------------------------- /GusUtils.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | EC5091511378582800BCF230 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC5091501378582800BCF230 /* Foundation.framework */; }; 11 | EC50915C1378582800BCF230 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC50915B1378582800BCF230 /* UIKit.framework */; }; 12 | EC50915D1378582800BCF230 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC5091501378582800BCF230 /* Foundation.framework */; }; 13 | EC50915F1378582800BCF230 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EC50915E1378582800BCF230 /* CoreGraphics.framework */; }; 14 | EC5091621378582800BCF230 /* libGusUtils.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EC50914D1378582800BCF230 /* libGusUtils.a */; }; 15 | EC5091681378582800BCF230 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = EC5091661378582800BCF230 /* InfoPlist.strings */; }; 16 | EC50916B1378582800BCF230 /* GusUtilsTests.h in Resources */ = {isa = PBXBuildFile; fileRef = EC50916A1378582800BCF230 /* GusUtilsTests.h */; }; 17 | EC50916D1378582800BCF230 /* GusUtilsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = EC50916C1378582800BCF230 /* GusUtilsTests.m */; }; 18 | EC5091791378583B00BCF230 /* NSMutableDictionary+ImageMetadata.m in Sources */ = {isa = PBXBuildFile; fileRef = EC5091771378583B00BCF230 /* NSMutableDictionary+ImageMetadata.m */; }; 19 | /* End PBXBuildFile section */ 20 | 21 | /* Begin PBXContainerItemProxy section */ 22 | EC5091601378582800BCF230 /* PBXContainerItemProxy */ = { 23 | isa = PBXContainerItemProxy; 24 | containerPortal = EC5091441378582800BCF230 /* Project object */; 25 | proxyType = 1; 26 | remoteGlobalIDString = EC50914C1378582800BCF230; 27 | remoteInfo = GusUtils; 28 | }; 29 | /* End PBXContainerItemProxy section */ 30 | 31 | /* Begin PBXFileReference section */ 32 | EC50914D1378582800BCF230 /* libGusUtils.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libGusUtils.a; sourceTree = BUILT_PRODUCTS_DIR; }; 33 | EC5091501378582800BCF230 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 34 | EC5091541378582800BCF230 /* GusUtils-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "GusUtils-Prefix.pch"; sourceTree = ""; }; 35 | EC50915A1378582800BCF230 /* GusUtilsTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GusUtilsTests.octest; sourceTree = BUILT_PRODUCTS_DIR; }; 36 | EC50915B1378582800BCF230 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 37 | EC50915E1378582800BCF230 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 38 | EC5091651378582800BCF230 /* GusUtilsTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GusUtilsTests-Info.plist"; sourceTree = ""; }; 39 | EC5091671378582800BCF230 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 40 | EC5091691378582800BCF230 /* GusUtilsTests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "GusUtilsTests-Prefix.pch"; sourceTree = ""; }; 41 | EC50916A1378582800BCF230 /* GusUtilsTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GusUtilsTests.h; sourceTree = ""; }; 42 | EC50916C1378582800BCF230 /* GusUtilsTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GusUtilsTests.m; sourceTree = ""; }; 43 | EC5091761378583B00BCF230 /* NSMutableDictionary+ImageMetadata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableDictionary+ImageMetadata.h"; sourceTree = ""; }; 44 | EC5091771378583B00BCF230 /* NSMutableDictionary+ImageMetadata.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableDictionary+ImageMetadata.m"; sourceTree = ""; }; 45 | /* End PBXFileReference section */ 46 | 47 | /* Begin PBXFrameworksBuildPhase section */ 48 | EC50914A1378582800BCF230 /* Frameworks */ = { 49 | isa = PBXFrameworksBuildPhase; 50 | buildActionMask = 2147483647; 51 | files = ( 52 | EC5091511378582800BCF230 /* Foundation.framework in Frameworks */, 53 | ); 54 | runOnlyForDeploymentPostprocessing = 0; 55 | }; 56 | EC5091561378582800BCF230 /* Frameworks */ = { 57 | isa = PBXFrameworksBuildPhase; 58 | buildActionMask = 2147483647; 59 | files = ( 60 | EC50915C1378582800BCF230 /* UIKit.framework in Frameworks */, 61 | EC50915D1378582800BCF230 /* Foundation.framework in Frameworks */, 62 | EC50915F1378582800BCF230 /* CoreGraphics.framework in Frameworks */, 63 | EC5091621378582800BCF230 /* libGusUtils.a in Frameworks */, 64 | ); 65 | runOnlyForDeploymentPostprocessing = 0; 66 | }; 67 | /* End PBXFrameworksBuildPhase section */ 68 | 69 | /* Begin PBXGroup section */ 70 | EC5091421378582800BCF230 = { 71 | isa = PBXGroup; 72 | children = ( 73 | EC5091521378582800BCF230 /* GusUtils */, 74 | EC5091631378582800BCF230 /* GusUtilsTests */, 75 | EC50914F1378582800BCF230 /* Frameworks */, 76 | EC50914E1378582800BCF230 /* Products */, 77 | ); 78 | sourceTree = ""; 79 | }; 80 | EC50914E1378582800BCF230 /* Products */ = { 81 | isa = PBXGroup; 82 | children = ( 83 | EC50914D1378582800BCF230 /* libGusUtils.a */, 84 | EC50915A1378582800BCF230 /* GusUtilsTests.octest */, 85 | ); 86 | name = Products; 87 | sourceTree = ""; 88 | }; 89 | EC50914F1378582800BCF230 /* Frameworks */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | EC5091501378582800BCF230 /* Foundation.framework */, 93 | EC50915B1378582800BCF230 /* UIKit.framework */, 94 | EC50915E1378582800BCF230 /* CoreGraphics.framework */, 95 | ); 96 | name = Frameworks; 97 | sourceTree = ""; 98 | }; 99 | EC5091521378582800BCF230 /* GusUtils */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | EC5091761378583B00BCF230 /* NSMutableDictionary+ImageMetadata.h */, 103 | EC5091771378583B00BCF230 /* NSMutableDictionary+ImageMetadata.m */, 104 | EC5091531378582800BCF230 /* Supporting Files */, 105 | ); 106 | path = GusUtils; 107 | sourceTree = ""; 108 | }; 109 | EC5091531378582800BCF230 /* Supporting Files */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | EC5091541378582800BCF230 /* GusUtils-Prefix.pch */, 113 | ); 114 | name = "Supporting Files"; 115 | sourceTree = ""; 116 | }; 117 | EC5091631378582800BCF230 /* GusUtilsTests */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | EC50916A1378582800BCF230 /* GusUtilsTests.h */, 121 | EC50916C1378582800BCF230 /* GusUtilsTests.m */, 122 | EC5091641378582800BCF230 /* Supporting Files */, 123 | ); 124 | path = GusUtilsTests; 125 | sourceTree = ""; 126 | }; 127 | EC5091641378582800BCF230 /* Supporting Files */ = { 128 | isa = PBXGroup; 129 | children = ( 130 | EC5091651378582800BCF230 /* GusUtilsTests-Info.plist */, 131 | EC5091661378582800BCF230 /* InfoPlist.strings */, 132 | EC5091691378582800BCF230 /* GusUtilsTests-Prefix.pch */, 133 | ); 134 | name = "Supporting Files"; 135 | sourceTree = ""; 136 | }; 137 | /* End PBXGroup section */ 138 | 139 | /* Begin PBXHeadersBuildPhase section */ 140 | EC50914B1378582800BCF230 /* Headers */ = { 141 | isa = PBXHeadersBuildPhase; 142 | buildActionMask = 2147483647; 143 | files = ( 144 | ); 145 | runOnlyForDeploymentPostprocessing = 0; 146 | }; 147 | /* End PBXHeadersBuildPhase section */ 148 | 149 | /* Begin PBXNativeTarget section */ 150 | EC50914C1378582800BCF230 /* GusUtils */ = { 151 | isa = PBXNativeTarget; 152 | buildConfigurationList = EC5091701378582800BCF230 /* Build configuration list for PBXNativeTarget "GusUtils" */; 153 | buildPhases = ( 154 | EC5091491378582800BCF230 /* Sources */, 155 | EC50914A1378582800BCF230 /* Frameworks */, 156 | EC50914B1378582800BCF230 /* Headers */, 157 | ); 158 | buildRules = ( 159 | ); 160 | dependencies = ( 161 | ); 162 | name = GusUtils; 163 | productName = GusUtils; 164 | productReference = EC50914D1378582800BCF230 /* libGusUtils.a */; 165 | productType = "com.apple.product-type.library.static"; 166 | }; 167 | EC5091591378582800BCF230 /* GusUtilsTests */ = { 168 | isa = PBXNativeTarget; 169 | buildConfigurationList = EC5091731378582800BCF230 /* Build configuration list for PBXNativeTarget "GusUtilsTests" */; 170 | buildPhases = ( 171 | EC5091551378582800BCF230 /* Sources */, 172 | EC5091561378582800BCF230 /* Frameworks */, 173 | EC5091571378582800BCF230 /* Resources */, 174 | EC5091581378582800BCF230 /* ShellScript */, 175 | ); 176 | buildRules = ( 177 | ); 178 | dependencies = ( 179 | EC5091611378582800BCF230 /* PBXTargetDependency */, 180 | ); 181 | name = GusUtilsTests; 182 | productName = GusUtilsTests; 183 | productReference = EC50915A1378582800BCF230 /* GusUtilsTests.octest */; 184 | productType = "com.apple.product-type.bundle"; 185 | }; 186 | /* End PBXNativeTarget section */ 187 | 188 | /* Begin PBXProject section */ 189 | EC5091441378582800BCF230 /* Project object */ = { 190 | isa = PBXProject; 191 | attributes = { 192 | LastUpgradeCheck = 1140; 193 | ORGANIZATIONNAME = "CodeCrop Software"; 194 | }; 195 | buildConfigurationList = EC5091471378582800BCF230 /* Build configuration list for PBXProject "GusUtils" */; 196 | compatibilityVersion = "Xcode 3.2"; 197 | developmentRegion = en; 198 | hasScannedForEncodings = 0; 199 | knownRegions = ( 200 | en, 201 | Base, 202 | ); 203 | mainGroup = EC5091421378582800BCF230; 204 | productRefGroup = EC50914E1378582800BCF230 /* Products */; 205 | projectDirPath = ""; 206 | projectRoot = ""; 207 | targets = ( 208 | EC50914C1378582800BCF230 /* GusUtils */, 209 | EC5091591378582800BCF230 /* GusUtilsTests */, 210 | ); 211 | }; 212 | /* End PBXProject section */ 213 | 214 | /* Begin PBXResourcesBuildPhase section */ 215 | EC5091571378582800BCF230 /* Resources */ = { 216 | isa = PBXResourcesBuildPhase; 217 | buildActionMask = 2147483647; 218 | files = ( 219 | EC5091681378582800BCF230 /* InfoPlist.strings in Resources */, 220 | EC50916B1378582800BCF230 /* GusUtilsTests.h in Resources */, 221 | ); 222 | runOnlyForDeploymentPostprocessing = 0; 223 | }; 224 | /* End PBXResourcesBuildPhase section */ 225 | 226 | /* Begin PBXShellScriptBuildPhase section */ 227 | EC5091581378582800BCF230 /* ShellScript */ = { 228 | isa = PBXShellScriptBuildPhase; 229 | buildActionMask = 2147483647; 230 | files = ( 231 | ); 232 | inputPaths = ( 233 | ); 234 | outputPaths = ( 235 | ); 236 | runOnlyForDeploymentPostprocessing = 0; 237 | shellPath = /bin/sh; 238 | shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n"; 239 | }; 240 | /* End PBXShellScriptBuildPhase section */ 241 | 242 | /* Begin PBXSourcesBuildPhase section */ 243 | EC5091491378582800BCF230 /* Sources */ = { 244 | isa = PBXSourcesBuildPhase; 245 | buildActionMask = 2147483647; 246 | files = ( 247 | EC5091791378583B00BCF230 /* NSMutableDictionary+ImageMetadata.m in Sources */, 248 | ); 249 | runOnlyForDeploymentPostprocessing = 0; 250 | }; 251 | EC5091551378582800BCF230 /* Sources */ = { 252 | isa = PBXSourcesBuildPhase; 253 | buildActionMask = 2147483647; 254 | files = ( 255 | EC50916D1378582800BCF230 /* GusUtilsTests.m in Sources */, 256 | ); 257 | runOnlyForDeploymentPostprocessing = 0; 258 | }; 259 | /* End PBXSourcesBuildPhase section */ 260 | 261 | /* Begin PBXTargetDependency section */ 262 | EC5091611378582800BCF230 /* PBXTargetDependency */ = { 263 | isa = PBXTargetDependency; 264 | target = EC50914C1378582800BCF230 /* GusUtils */; 265 | targetProxy = EC5091601378582800BCF230 /* PBXContainerItemProxy */; 266 | }; 267 | /* End PBXTargetDependency section */ 268 | 269 | /* Begin PBXVariantGroup section */ 270 | EC5091661378582800BCF230 /* InfoPlist.strings */ = { 271 | isa = PBXVariantGroup; 272 | children = ( 273 | EC5091671378582800BCF230 /* en */, 274 | ); 275 | name = InfoPlist.strings; 276 | sourceTree = ""; 277 | }; 278 | /* End PBXVariantGroup section */ 279 | 280 | /* Begin XCBuildConfiguration section */ 281 | EC50916E1378582800BCF230 /* Debug */ = { 282 | isa = XCBuildConfiguration; 283 | buildSettings = { 284 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 285 | ENABLE_TESTABILITY = YES; 286 | GCC_C_LANGUAGE_STANDARD = gnu99; 287 | GCC_OPTIMIZATION_LEVEL = 0; 288 | GCC_PREPROCESSOR_DEFINITIONS = DEBUG; 289 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 290 | GCC_VERSION = com.apple.compilers.llvmgcc42; 291 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 292 | GCC_WARN_UNUSED_VARIABLE = YES; 293 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 294 | ONLY_ACTIVE_ARCH = YES; 295 | SDKROOT = iphoneos; 296 | }; 297 | name = Debug; 298 | }; 299 | EC50916F1378582800BCF230 /* Release */ = { 300 | isa = XCBuildConfiguration; 301 | buildSettings = { 302 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 303 | GCC_C_LANGUAGE_STANDARD = gnu99; 304 | GCC_VERSION = com.apple.compilers.llvmgcc42; 305 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 306 | GCC_WARN_UNUSED_VARIABLE = YES; 307 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 308 | SDKROOT = iphoneos; 309 | }; 310 | name = Release; 311 | }; 312 | EC5091711378582800BCF230 /* Debug */ = { 313 | isa = XCBuildConfiguration; 314 | buildSettings = { 315 | ALWAYS_SEARCH_USER_PATHS = NO; 316 | CLANG_ENABLE_OBJC_WEAK = YES; 317 | DSTROOT = /tmp/GusUtils.dst; 318 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 319 | GCC_PREFIX_HEADER = "GusUtils/GusUtils-Prefix.pch"; 320 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 321 | OTHER_LDFLAGS = "-ObjC"; 322 | PRODUCT_NAME = "$(TARGET_NAME)"; 323 | }; 324 | name = Debug; 325 | }; 326 | EC5091721378582800BCF230 /* Release */ = { 327 | isa = XCBuildConfiguration; 328 | buildSettings = { 329 | ALWAYS_SEARCH_USER_PATHS = NO; 330 | CLANG_ENABLE_OBJC_WEAK = YES; 331 | DSTROOT = /tmp/GusUtils.dst; 332 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 333 | GCC_PREFIX_HEADER = "GusUtils/GusUtils-Prefix.pch"; 334 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 335 | OTHER_LDFLAGS = "-ObjC"; 336 | PRODUCT_NAME = "$(TARGET_NAME)"; 337 | }; 338 | name = Release; 339 | }; 340 | EC5091741378582800BCF230 /* Debug */ = { 341 | isa = XCBuildConfiguration; 342 | buildSettings = { 343 | ALWAYS_SEARCH_USER_PATHS = NO; 344 | CLANG_ENABLE_OBJC_WEAK = YES; 345 | FRAMEWORK_SEARCH_PATHS = ( 346 | "$(SDKROOT)/Developer/Library/Frameworks", 347 | "$(DEVELOPER_LIBRARY_DIR)/Frameworks", 348 | ); 349 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 350 | GCC_PREFIX_HEADER = "GusUtilsTests/GusUtilsTests-Prefix.pch"; 351 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 352 | INFOPLIST_FILE = "GusUtilsTests/GusUtilsTests-Info.plist"; 353 | OTHER_LDFLAGS = ( 354 | "-framework", 355 | SenTestingKit, 356 | ); 357 | PRODUCT_BUNDLE_IDENTIFIER = "___VARIABLE_bundleIdentifierPrefix:bundleIdentifier___.${PRODUCT_NAME:rfc1034identifier}"; 358 | PRODUCT_NAME = "$(TARGET_NAME)"; 359 | WRAPPER_EXTENSION = octest; 360 | }; 361 | name = Debug; 362 | }; 363 | EC5091751378582800BCF230 /* Release */ = { 364 | isa = XCBuildConfiguration; 365 | buildSettings = { 366 | ALWAYS_SEARCH_USER_PATHS = NO; 367 | CLANG_ENABLE_OBJC_WEAK = YES; 368 | FRAMEWORK_SEARCH_PATHS = ( 369 | "$(SDKROOT)/Developer/Library/Frameworks", 370 | "$(DEVELOPER_LIBRARY_DIR)/Frameworks", 371 | ); 372 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 373 | GCC_PREFIX_HEADER = "GusUtilsTests/GusUtilsTests-Prefix.pch"; 374 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 375 | INFOPLIST_FILE = "GusUtilsTests/GusUtilsTests-Info.plist"; 376 | OTHER_LDFLAGS = ( 377 | "-framework", 378 | SenTestingKit, 379 | ); 380 | PRODUCT_BUNDLE_IDENTIFIER = "___VARIABLE_bundleIdentifierPrefix:bundleIdentifier___.${PRODUCT_NAME:rfc1034identifier}"; 381 | PRODUCT_NAME = "$(TARGET_NAME)"; 382 | WRAPPER_EXTENSION = octest; 383 | }; 384 | name = Release; 385 | }; 386 | /* End XCBuildConfiguration section */ 387 | 388 | /* Begin XCConfigurationList section */ 389 | EC5091471378582800BCF230 /* Build configuration list for PBXProject "GusUtils" */ = { 390 | isa = XCConfigurationList; 391 | buildConfigurations = ( 392 | EC50916E1378582800BCF230 /* Debug */, 393 | EC50916F1378582800BCF230 /* Release */, 394 | ); 395 | defaultConfigurationIsVisible = 0; 396 | defaultConfigurationName = Release; 397 | }; 398 | EC5091701378582800BCF230 /* Build configuration list for PBXNativeTarget "GusUtils" */ = { 399 | isa = XCConfigurationList; 400 | buildConfigurations = ( 401 | EC5091711378582800BCF230 /* Debug */, 402 | EC5091721378582800BCF230 /* Release */, 403 | ); 404 | defaultConfigurationIsVisible = 0; 405 | defaultConfigurationName = Release; 406 | }; 407 | EC5091731378582800BCF230 /* Build configuration list for PBXNativeTarget "GusUtilsTests" */ = { 408 | isa = XCConfigurationList; 409 | buildConfigurations = ( 410 | EC5091741378582800BCF230 /* Debug */, 411 | EC5091751378582800BCF230 /* Release */, 412 | ); 413 | defaultConfigurationIsVisible = 0; 414 | defaultConfigurationName = Release; 415 | }; 416 | /* End XCConfigurationList section */ 417 | }; 418 | rootObject = EC5091441378582800BCF230 /* Project object */; 419 | } 420 | --------------------------------------------------------------------------------