├── LICENSE ├── NSData+reallyMapped.h ├── NSData+reallyMapped.m ├── NSObject+deallocBlock.h ├── NSObject+deallocBlock.m ├── NSObject+setValuesForKeysWithJSONDictionary.h ├── NSObject+setValuesForKeysWithJSONDictionary.m ├── README.md ├── Sample Code └── SetJSONDemo │ ├── SetJSONDemo.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── tph.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── tph.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints.xcbkptlist │ │ └── xcschemes │ │ ├── SetJSONDemo.xcscheme │ │ └── xcschememanagement.plist │ └── SetJSONDemo │ ├── SetJSONDemo-Prefix.pch │ ├── SetJSONDemo.1 │ ├── TestClass.h │ ├── TestClass.m │ └── main.m └── fixpng.sh /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Tom Harrington (tph@atomicbird.com) 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. 20 | -------------------------------------------------------------------------------- /NSData+reallyMapped.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+reallyMapped.h 3 | // MapTest 4 | // 5 | // Created by Tom Harrington on 1/31/12. 6 | // Copyright (c) 2012 Atomic Bird, LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSData (reallyMapped) 12 | 13 | + (NSData *)dataWithContentsOfReallyMappedFile:(NSString *)path; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /NSData+reallyMapped.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+reallyMapped.m 3 | // MapTest 4 | // 5 | // Created by Tom Harrington on 1/31/12. 6 | // Copyright (c) 2012 Atomic Bird, LLC. All rights reserved. 7 | // 8 | 9 | #import "NSData+reallyMapped.h" 10 | #import 11 | #import 12 | #include 13 | #import "NSObject+deallocBlock.h" 14 | 15 | @implementation NSData (reallyMapped) 16 | 17 | + (NSData *)dataWithContentsOfReallyMappedFile:(NSString *)path; 18 | { 19 | // Get an fd 20 | int fd = open([path fileSystemRepresentation], O_RDONLY); 21 | if (fd < 0) { 22 | return nil; 23 | } 24 | 25 | // Get file size 26 | struct stat statbuf; 27 | if (fstat(fd, &statbuf) == -1) { 28 | close(fd); 29 | return nil; 30 | } 31 | 32 | // mmap 33 | void *mappedFile; 34 | mappedFile = mmap(0, statbuf.st_size, PROT_READ, MAP_FILE|MAP_PRIVATE, fd, 0); 35 | close(fd); 36 | if (mappedFile == MAP_FAILED) { 37 | NSLog(@"Map failed, errno=%d, %s", errno, strerror(errno)); 38 | return nil; 39 | } 40 | 41 | // Create the NSData 42 | NSData *mappedData = [NSData dataWithBytesNoCopy:mappedFile length:statbuf.st_size freeWhenDone:NO]; 43 | 44 | [mappedData addDeallocBlock:^{ 45 | munmap(mappedFile, statbuf.st_size); 46 | }]; 47 | return mappedData; 48 | } 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /NSObject+deallocBlock.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+deallocBlock.h 3 | // MapTest 4 | // 5 | // Created by Tom Harrington on 2/5/12. 6 | // Copyright (c) 2012 Atomic Bird, LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSObject (deallocBlock) 12 | 13 | - (void)addDeallocBlock:(void (^)(void))theBlock; 14 | @end 15 | -------------------------------------------------------------------------------- /NSObject+deallocBlock.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+deallocBlock.m 3 | // MapTest 4 | // 5 | // Created by Tom Harrington on 2/5/12. 6 | // Copyright (c) 2012 Atomic Bird, LLC. All rights reserved. 7 | // 8 | 9 | #import "NSObject+deallocBlock.h" 10 | #import 11 | 12 | static char *deallocArrayKey = "deallocArrayKey"; 13 | 14 | // This class exists for the sole purpose of holding a block that it executes before getting deallocated. 15 | @interface DeallocHandler : NSObject 16 | @property (readwrite, copy) void (^theBlock)(void); 17 | @end 18 | 19 | @implementation DeallocHandler 20 | @synthesize theBlock; 21 | 22 | - (void)dealloc 23 | { 24 | if (theBlock != nil) { 25 | theBlock(); 26 | } 27 | } 28 | @end 29 | 30 | @implementation NSObject (deallocBlock) 31 | 32 | - (void)addDeallocBlock:(void (^)(void))theBlock; 33 | { 34 | NSMutableArray *deallocBlocks = objc_getAssociatedObject(self, &deallocArrayKey); 35 | if (deallocBlocks == nil) { 36 | deallocBlocks = [NSMutableArray array]; 37 | objc_setAssociatedObject(self, &deallocArrayKey, deallocBlocks, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 38 | } 39 | DeallocHandler *handler = [[DeallocHandler alloc] init]; 40 | [handler setTheBlock:theBlock]; 41 | [deallocBlocks addObject:handler]; 42 | } 43 | @end 44 | -------------------------------------------------------------------------------- /NSObject+setValuesForKeysWithJSONDictionary.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+setValuesForKeysWithJSONDictionary.h 3 | // SafeSetDemo 4 | // 5 | // Created by Tom Harrington on 12/29/11. 6 | // Copyright (c) 2011 Atomic Bird, LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSObject (setValuesForKeysWithJSONDictionary) 12 | 13 | - (void)setValuesForKeysWithJSONDictionary:(NSDictionary *)keyedValues dateFormatter:(NSDateFormatter *)dateFormatter; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /NSObject+setValuesForKeysWithJSONDictionary.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+setValuesForKeysWithJSONDictionary.m 3 | // SafeSetDemo 4 | // 5 | // Created by Tom Harrington on 12/29/11. 6 | // Copyright (c) 2011 Atomic Bird, LLC. All rights reserved. 7 | // 8 | 9 | #import "NSObject+setValuesForKeysWithJSONDictionary.h" 10 | #import 11 | 12 | @implementation NSObject (setValuesForKeysWithJSONDictionary) 13 | 14 | - (void)setValuesForKeysWithJSONDictionary:(NSDictionary *)keyedValues dateFormatter:(NSDateFormatter *)dateFormatter 15 | { 16 | unsigned int propertyCount; 17 | objc_property_t *properties = class_copyPropertyList([self class], &propertyCount); 18 | 19 | /* 20 | This code starts by over self's properties instead of ivars because the backing ivar might have a different name 21 | than the property, for example if the class includes something like: 22 | 23 | @synthesize foo = foo_; 24 | 25 | In this case what we probably want is "foo", not "foo_", since the incoming keys in keyedValues probably 26 | don't have the underscore. Looking through properties gets "foo", looking through ivars gets "foo_". 27 | 28 | If there's no property name that matches the incoming key name, the code checks the ivars as well. 29 | */ 30 | for (int i=0; i= 3) { 59 | char *className = strndup(typeEncoding+2, strlen(typeEncoding)-3); 60 | class = NSClassFromString([NSString stringWithUTF8String:className]); 61 | free(className); 62 | } 63 | // Check for type mismatch, attempt to compensate 64 | if ([class isSubclassOfClass:[NSString class]] && [value isKindOfClass:[NSNumber class]]) { 65 | value = [value stringValue]; 66 | } else if ([class isSubclassOfClass:[NSNumber class]] && [value isKindOfClass:[NSString class]]) { 67 | // If the ivar is an NSNumber we really can't tell if it's intended as an integer, float, etc. 68 | NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; 69 | [numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle]; 70 | value = [numberFormatter numberFromString:value]; 71 | } else if ([class isSubclassOfClass:[NSDate class]] && [value isKindOfClass:[NSString class]] && (dateFormatter != nil)) { 72 | value = [dateFormatter dateFromString:value]; 73 | } 74 | 75 | break; 76 | } 77 | 78 | case 'i': // int 79 | case 's': // short 80 | case 'l': // long 81 | case 'q': // long long 82 | case 'I': // unsigned int 83 | case 'S': // unsigned short 84 | case 'L': // unsigned long 85 | case 'Q': // unsigned long long 86 | case 'f': // float 87 | case 'd': // double 88 | case 'B': // BOOL 89 | { 90 | if ([value isKindOfClass:[NSString class]]) { 91 | NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; 92 | [numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle]; 93 | value = [numberFormatter numberFromString:value]; 94 | } 95 | break; 96 | } 97 | 98 | case 'c': // char 99 | case 'C': // unsigned char 100 | { 101 | if ([value isKindOfClass:[NSString class]]) { 102 | char firstCharacter = [value characterAtIndex:0]; 103 | value = [NSNumber numberWithChar:firstCharacter]; 104 | } 105 | break; 106 | } 107 | 108 | default: 109 | { 110 | break; 111 | } 112 | } 113 | [self setValue:value forKey:keyName]; 114 | free(typeEncoding); 115 | } 116 | } 117 | free(properties); 118 | } 119 | 120 | @end 121 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Atomic Tools 2 | 3 | A collection of useful Objective-C code and other items of use to iOS and Mac OS X developers. Most of this has been blogged about at [Cocoa is my Girlfriend](http://www.cimgf.com/). 4 | 5 | * `NSObject+setValuesForKeysWithJSONDictionary.h`: Safer alternative to `setValuesForKeysWithDictionary:` for use when importing JSON. Works with any object with declared properties corresponding to JSON dictionary keys. Detailed discussion is at [CIMGF](http://www.cimgf.com/2012/01/11/handling-incoming-json-redux/). 6 | 7 | * `NSObject+deallocBlock.h`: Add a block to any object that will execute when that object is deallocated. Described in detail at [CIMGF](http://www.cimgf.com/2012/02/17/extending-nsdata-and-not-overriding-dealloc/). 8 | 9 | * `NSData+reallyMapped.h`: Create an NSData object using a memory mapped file. Works even though `dataWithContentsOfMappedFile:` is deprecated in iOS 5.0 and `NSDataReadingMappedAlways` doesn't always (despite the name) create memory mapped instances. Described in detail at [CIMGF](http://www.cimgf.com/2012/02/17/extending-nsdata-and-not-overriding-dealloc/). 10 | 11 | * `fixpng.sh`: Two bash functions useful for converting iOS-optimized PNGs back into standard PNGs. These functions rely on the `xcrun` command-line tool and probably require that Xcode 4.3 or higher be installed. Based on Daniel Jalkut's [zsh version](https://gist.github.com/2854083). 12 | 13 | # Important note 14 | 15 | All Objective-C code in this repository is designed for use with automated reference counting (ARC). If you are not using ARC you may experience memory leaks or worse. 16 | -------------------------------------------------------------------------------- /Sample Code/SetJSONDemo/SetJSONDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | EE776C7F14F40E220009E9D9 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE776C7E14F40E220009E9D9 /* Foundation.framework */; }; 11 | EE776C8214F40E220009E9D9 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = EE776C8114F40E220009E9D9 /* main.m */; }; 12 | EE776C8614F40E220009E9D9 /* SetJSONDemo.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = EE776C8514F40E220009E9D9 /* SetJSONDemo.1 */; }; 13 | EE776C8E14F40E420009E9D9 /* TestClass.m in Sources */ = {isa = PBXBuildFile; fileRef = EE776C8D14F40E420009E9D9 /* TestClass.m */; }; 14 | EE776C9114F40E5E0009E9D9 /* NSObject+setValuesForKeysWithJSONDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = EE776C9014F40E5E0009E9D9 /* NSObject+setValuesForKeysWithJSONDictionary.m */; }; 15 | /* End PBXBuildFile section */ 16 | 17 | /* Begin PBXCopyFilesBuildPhase section */ 18 | EE776C7814F40E220009E9D9 /* CopyFiles */ = { 19 | isa = PBXCopyFilesBuildPhase; 20 | buildActionMask = 2147483647; 21 | dstPath = /usr/share/man/man1/; 22 | dstSubfolderSpec = 0; 23 | files = ( 24 | EE776C8614F40E220009E9D9 /* SetJSONDemo.1 in CopyFiles */, 25 | ); 26 | runOnlyForDeploymentPostprocessing = 1; 27 | }; 28 | /* End PBXCopyFilesBuildPhase section */ 29 | 30 | /* Begin PBXFileReference section */ 31 | EE776C7A14F40E220009E9D9 /* SetJSONDemo */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = SetJSONDemo; sourceTree = BUILT_PRODUCTS_DIR; }; 32 | EE776C7E14F40E220009E9D9 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 33 | EE776C8114F40E220009E9D9 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 34 | EE776C8414F40E220009E9D9 /* SetJSONDemo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SetJSONDemo-Prefix.pch"; sourceTree = ""; }; 35 | EE776C8514F40E220009E9D9 /* SetJSONDemo.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = SetJSONDemo.1; sourceTree = ""; }; 36 | EE776C8C14F40E420009E9D9 /* TestClass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TestClass.h; sourceTree = ""; }; 37 | EE776C8D14F40E420009E9D9 /* TestClass.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TestClass.m; sourceTree = ""; }; 38 | EE776C8F14F40E5E0009E9D9 /* NSObject+setValuesForKeysWithJSONDictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSObject+setValuesForKeysWithJSONDictionary.h"; path = "../../../NSObject+setValuesForKeysWithJSONDictionary.h"; sourceTree = ""; }; 39 | EE776C9014F40E5E0009E9D9 /* NSObject+setValuesForKeysWithJSONDictionary.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSObject+setValuesForKeysWithJSONDictionary.m"; path = "../../../NSObject+setValuesForKeysWithJSONDictionary.m"; sourceTree = ""; }; 40 | /* End PBXFileReference section */ 41 | 42 | /* Begin PBXFrameworksBuildPhase section */ 43 | EE776C7714F40E220009E9D9 /* Frameworks */ = { 44 | isa = PBXFrameworksBuildPhase; 45 | buildActionMask = 2147483647; 46 | files = ( 47 | EE776C7F14F40E220009E9D9 /* Foundation.framework in Frameworks */, 48 | ); 49 | runOnlyForDeploymentPostprocessing = 0; 50 | }; 51 | /* End PBXFrameworksBuildPhase section */ 52 | 53 | /* Begin PBXGroup section */ 54 | EE776C6F14F40E220009E9D9 = { 55 | isa = PBXGroup; 56 | children = ( 57 | EE776C8014F40E220009E9D9 /* SetJSONDemo */, 58 | EE776C7D14F40E220009E9D9 /* Frameworks */, 59 | EE776C7B14F40E220009E9D9 /* Products */, 60 | ); 61 | sourceTree = ""; 62 | }; 63 | EE776C7B14F40E220009E9D9 /* Products */ = { 64 | isa = PBXGroup; 65 | children = ( 66 | EE776C7A14F40E220009E9D9 /* SetJSONDemo */, 67 | ); 68 | name = Products; 69 | sourceTree = ""; 70 | }; 71 | EE776C7D14F40E220009E9D9 /* Frameworks */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | EE776C7E14F40E220009E9D9 /* Foundation.framework */, 75 | ); 76 | name = Frameworks; 77 | sourceTree = ""; 78 | }; 79 | EE776C8014F40E220009E9D9 /* SetJSONDemo */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | EE776C8114F40E220009E9D9 /* main.m */, 83 | EE776C8C14F40E420009E9D9 /* TestClass.h */, 84 | EE776C8D14F40E420009E9D9 /* TestClass.m */, 85 | EE776C8F14F40E5E0009E9D9 /* NSObject+setValuesForKeysWithJSONDictionary.h */, 86 | EE776C9014F40E5E0009E9D9 /* NSObject+setValuesForKeysWithJSONDictionary.m */, 87 | EE776C8514F40E220009E9D9 /* SetJSONDemo.1 */, 88 | EE776C8314F40E220009E9D9 /* Supporting Files */, 89 | ); 90 | path = SetJSONDemo; 91 | sourceTree = ""; 92 | }; 93 | EE776C8314F40E220009E9D9 /* Supporting Files */ = { 94 | isa = PBXGroup; 95 | children = ( 96 | EE776C8414F40E220009E9D9 /* SetJSONDemo-Prefix.pch */, 97 | ); 98 | name = "Supporting Files"; 99 | sourceTree = ""; 100 | }; 101 | /* End PBXGroup section */ 102 | 103 | /* Begin PBXNativeTarget section */ 104 | EE776C7914F40E220009E9D9 /* SetJSONDemo */ = { 105 | isa = PBXNativeTarget; 106 | buildConfigurationList = EE776C8914F40E220009E9D9 /* Build configuration list for PBXNativeTarget "SetJSONDemo" */; 107 | buildPhases = ( 108 | EE776C7614F40E220009E9D9 /* Sources */, 109 | EE776C7714F40E220009E9D9 /* Frameworks */, 110 | EE776C7814F40E220009E9D9 /* CopyFiles */, 111 | ); 112 | buildRules = ( 113 | ); 114 | dependencies = ( 115 | ); 116 | name = SetJSONDemo; 117 | productName = SetJSONDemo; 118 | productReference = EE776C7A14F40E220009E9D9 /* SetJSONDemo */; 119 | productType = "com.apple.product-type.tool"; 120 | }; 121 | /* End PBXNativeTarget section */ 122 | 123 | /* Begin PBXProject section */ 124 | EE776C7114F40E220009E9D9 /* Project object */ = { 125 | isa = PBXProject; 126 | attributes = { 127 | LastUpgradeCheck = 0430; 128 | ORGANIZATIONNAME = "Atomic Bird, LLC"; 129 | }; 130 | buildConfigurationList = EE776C7414F40E220009E9D9 /* Build configuration list for PBXProject "SetJSONDemo" */; 131 | compatibilityVersion = "Xcode 3.2"; 132 | developmentRegion = English; 133 | hasScannedForEncodings = 0; 134 | knownRegions = ( 135 | en, 136 | ); 137 | mainGroup = EE776C6F14F40E220009E9D9; 138 | productRefGroup = EE776C7B14F40E220009E9D9 /* Products */; 139 | projectDirPath = ""; 140 | projectRoot = ""; 141 | targets = ( 142 | EE776C7914F40E220009E9D9 /* SetJSONDemo */, 143 | ); 144 | }; 145 | /* End PBXProject section */ 146 | 147 | /* Begin PBXSourcesBuildPhase section */ 148 | EE776C7614F40E220009E9D9 /* Sources */ = { 149 | isa = PBXSourcesBuildPhase; 150 | buildActionMask = 2147483647; 151 | files = ( 152 | EE776C8214F40E220009E9D9 /* main.m in Sources */, 153 | EE776C8E14F40E420009E9D9 /* TestClass.m in Sources */, 154 | EE776C9114F40E5E0009E9D9 /* NSObject+setValuesForKeysWithJSONDictionary.m in Sources */, 155 | ); 156 | runOnlyForDeploymentPostprocessing = 0; 157 | }; 158 | /* End PBXSourcesBuildPhase section */ 159 | 160 | /* Begin XCBuildConfiguration section */ 161 | EE776C8714F40E220009E9D9 /* Debug */ = { 162 | isa = XCBuildConfiguration; 163 | buildSettings = { 164 | ALWAYS_SEARCH_USER_PATHS = NO; 165 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 166 | CLANG_ENABLE_OBJC_ARC = YES; 167 | COPY_PHASE_STRIP = NO; 168 | GCC_C_LANGUAGE_STANDARD = gnu99; 169 | GCC_DYNAMIC_NO_PIC = NO; 170 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 171 | GCC_OPTIMIZATION_LEVEL = 0; 172 | GCC_PREPROCESSOR_DEFINITIONS = ( 173 | "DEBUG=1", 174 | "$(inherited)", 175 | ); 176 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 177 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 178 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 179 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 180 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 181 | GCC_WARN_UNUSED_VARIABLE = YES; 182 | MACOSX_DEPLOYMENT_TARGET = 10.7; 183 | ONLY_ACTIVE_ARCH = YES; 184 | SDKROOT = macosx; 185 | }; 186 | name = Debug; 187 | }; 188 | EE776C8814F40E220009E9D9 /* Release */ = { 189 | isa = XCBuildConfiguration; 190 | buildSettings = { 191 | ALWAYS_SEARCH_USER_PATHS = NO; 192 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 193 | CLANG_ENABLE_OBJC_ARC = YES; 194 | COPY_PHASE_STRIP = YES; 195 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 196 | GCC_C_LANGUAGE_STANDARD = gnu99; 197 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 198 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 199 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 200 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 201 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 202 | GCC_WARN_UNUSED_VARIABLE = YES; 203 | MACOSX_DEPLOYMENT_TARGET = 10.7; 204 | SDKROOT = macosx; 205 | }; 206 | name = Release; 207 | }; 208 | EE776C8A14F40E220009E9D9 /* Debug */ = { 209 | isa = XCBuildConfiguration; 210 | buildSettings = { 211 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 212 | GCC_PREFIX_HEADER = "SetJSONDemo/SetJSONDemo-Prefix.pch"; 213 | PRODUCT_NAME = "$(TARGET_NAME)"; 214 | }; 215 | name = Debug; 216 | }; 217 | EE776C8B14F40E220009E9D9 /* Release */ = { 218 | isa = XCBuildConfiguration; 219 | buildSettings = { 220 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 221 | GCC_PREFIX_HEADER = "SetJSONDemo/SetJSONDemo-Prefix.pch"; 222 | PRODUCT_NAME = "$(TARGET_NAME)"; 223 | }; 224 | name = Release; 225 | }; 226 | /* End XCBuildConfiguration section */ 227 | 228 | /* Begin XCConfigurationList section */ 229 | EE776C7414F40E220009E9D9 /* Build configuration list for PBXProject "SetJSONDemo" */ = { 230 | isa = XCConfigurationList; 231 | buildConfigurations = ( 232 | EE776C8714F40E220009E9D9 /* Debug */, 233 | EE776C8814F40E220009E9D9 /* Release */, 234 | ); 235 | defaultConfigurationIsVisible = 0; 236 | defaultConfigurationName = Release; 237 | }; 238 | EE776C8914F40E220009E9D9 /* Build configuration list for PBXNativeTarget "SetJSONDemo" */ = { 239 | isa = XCConfigurationList; 240 | buildConfigurations = ( 241 | EE776C8A14F40E220009E9D9 /* Debug */, 242 | EE776C8B14F40E220009E9D9 /* Release */, 243 | ); 244 | defaultConfigurationIsVisible = 0; 245 | }; 246 | /* End XCConfigurationList section */ 247 | }; 248 | rootObject = EE776C7114F40E220009E9D9 /* Project object */; 249 | } 250 | -------------------------------------------------------------------------------- /Sample Code/SetJSONDemo/SetJSONDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Sample Code/SetJSONDemo/SetJSONDemo.xcodeproj/project.xcworkspace/xcuserdata/tph.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/atomicbird/atomictools/b3dfbc685dbca0c9b24bde1fd3c3259d89198678/Sample Code/SetJSONDemo/SetJSONDemo.xcodeproj/project.xcworkspace/xcuserdata/tph.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /Sample Code/SetJSONDemo/SetJSONDemo.xcodeproj/xcuserdata/tph.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Sample Code/SetJSONDemo/SetJSONDemo.xcodeproj/xcuserdata/tph.xcuserdatad/xcschemes/SetJSONDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 14 | 20 | 21 | 22 | 23 | 24 | 29 | 30 | 31 | 32 | 38 | 39 | 40 | 41 | 50 | 51 | 57 | 58 | 59 | 60 | 61 | 62 | 68 | 69 | 75 | 76 | 77 | 78 | 80 | 81 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /Sample Code/SetJSONDemo/SetJSONDemo.xcodeproj/xcuserdata/tph.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SetJSONDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | EE776C7914F40E220009E9D9 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Sample Code/SetJSONDemo/SetJSONDemo/SetJSONDemo-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'SetJSONDemo' target in the 'SetJSONDemo' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /Sample Code/SetJSONDemo/SetJSONDemo/SetJSONDemo.1: -------------------------------------------------------------------------------- 1 | .\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. 2 | .\"See Also: 3 | .\"man mdoc.samples for a complete listing of options 4 | .\"man mdoc for the short list of editing options 5 | .\"/usr/share/misc/mdoc.template 6 | .Dd 2/21/12 \" DATE 7 | .Dt SetJSONDemo 1 \" Program name and manual section number 8 | .Os Darwin 9 | .Sh NAME \" Section Header - required - don't modify 10 | .Nm SetJSONDemo, 11 | .\" The following lines are read in generating the apropos(man -k) database. Use only key 12 | .\" words here as the database is built based on the words here and in the .ND line. 13 | .Nm Other_name_for_same_program(), 14 | .Nm Yet another name for the same program. 15 | .\" Use .Nm macro to designate other names for the documented program. 16 | .Nd This line parsed for whatis database. 17 | .Sh SYNOPSIS \" Section Header - required - don't modify 18 | .Nm 19 | .Op Fl abcd \" [-abcd] 20 | .Op Fl a Ar path \" [-a path] 21 | .Op Ar file \" [file] 22 | .Op Ar \" [file ...] 23 | .Ar arg0 \" Underlined argument - use .Ar anywhere to underline 24 | arg2 ... \" Arguments 25 | .Sh DESCRIPTION \" Section Header - required - don't modify 26 | Use the .Nm macro to refer to your program throughout the man page like such: 27 | .Nm 28 | Underlining is accomplished with the .Ar macro like this: 29 | .Ar underlined text . 30 | .Pp \" Inserts a space 31 | A list of items with descriptions: 32 | .Bl -tag -width -indent \" Begins a tagged list 33 | .It item a \" Each item preceded by .It macro 34 | Description of item a 35 | .It item b 36 | Description of item b 37 | .El \" Ends the list 38 | .Pp 39 | A list of flags and their descriptions: 40 | .Bl -tag -width -indent \" Differs from above in tag removed 41 | .It Fl a \"-a flag as a list item 42 | Description of -a flag 43 | .It Fl b 44 | Description of -b flag 45 | .El \" Ends the list 46 | .Pp 47 | .\" .Sh ENVIRONMENT \" May not be needed 48 | .\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1 49 | .\" .It Ev ENV_VAR_1 50 | .\" Description of ENV_VAR_1 51 | .\" .It Ev ENV_VAR_2 52 | .\" Description of ENV_VAR_2 53 | .\" .El 54 | .Sh FILES \" File used or created by the topic of the man page 55 | .Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact 56 | .It Pa /usr/share/file_name 57 | FILE_1 description 58 | .It Pa /Users/joeuser/Library/really_long_file_name 59 | FILE_2 description 60 | .El \" Ends the list 61 | .\" .Sh DIAGNOSTICS \" May not be needed 62 | .\" .Bl -diag 63 | .\" .It Diagnostic Tag 64 | .\" Diagnostic informtion here. 65 | .\" .It Diagnostic Tag 66 | .\" Diagnostic informtion here. 67 | .\" .El 68 | .Sh SEE ALSO 69 | .\" List links in ascending order by section, alphabetically within a section. 70 | .\" Please do not reference files that do not exist without filing a bug report 71 | .Xr a 1 , 72 | .Xr b 1 , 73 | .Xr c 1 , 74 | .Xr a 2 , 75 | .Xr b 2 , 76 | .Xr a 3 , 77 | .Xr b 3 78 | .\" .Sh BUGS \" Document known, unremedied bugs 79 | .\" .Sh HISTORY \" Document history if command behaves in a unique manner -------------------------------------------------------------------------------- /Sample Code/SetJSONDemo/SetJSONDemo/TestClass.h: -------------------------------------------------------------------------------- 1 | // 2 | // TestClass.h 3 | // SafeSetDemo 4 | // 5 | // Created by Tom Harrington on 12/29/11. 6 | // Copyright (c) 2011 Atomic Bird, LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TestClass : NSObject 12 | 13 | @property (readwrite, strong) NSDate *date; 14 | @property (readwrite, strong) NSString *string; 15 | @property (readwrite, strong) NSNumber *floatNumber; 16 | 17 | @property (readwrite, assign) NSUInteger unsignedInteger; 18 | 19 | @property (readwrite, assign) char character; 20 | @end 21 | -------------------------------------------------------------------------------- /Sample Code/SetJSONDemo/SetJSONDemo/TestClass.m: -------------------------------------------------------------------------------- 1 | // 2 | // TestClass.m 3 | // SafeSetDemo 4 | // 5 | // Created by Tom Harrington on 12/29/11. 6 | // Copyright (c) 2011 Atomic Bird, LLC. All rights reserved. 7 | // 8 | 9 | #import "TestClass.h" 10 | 11 | @implementation TestClass 12 | 13 | @synthesize date; 14 | @synthesize string = string_; 15 | @synthesize floatNumber; 16 | 17 | @synthesize unsignedInteger; 18 | @synthesize character; 19 | @end 20 | -------------------------------------------------------------------------------- /Sample Code/SetJSONDemo/SetJSONDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // SetJSONDemo 4 | // 5 | // Created by Tom Harrington on 2/21/12. 6 | // Copyright (c) 2012 Atomic Bird, LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NSObject+setValuesForKeysWithJSONDictionary.h" 11 | #import "TestClass.h" 12 | 13 | int main(int argc, const char * argv[]) 14 | { 15 | 16 | @autoreleasepool { 17 | 18 | TestClass *test = [[TestClass alloc] init]; 19 | 20 | NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 21 | [dateFormatter setDateFormat:@"yyyy-MM-dd'T'H:mm:ss"]; 22 | 23 | NSDictionary *dictionary; 24 | dictionary = [NSDictionary dictionaryWithObjectsAndKeys: 25 | [NSNumber numberWithInt:27], @"string", 26 | 27 | @"foo", @"bar", 28 | 29 | @"1.23", @"floatNumber", 30 | 31 | @"23", @"unsignedInteger", 32 | 33 | @"2011-12-29T17:36:27", @"date", 34 | 35 | @"xyz", @"character", 36 | nil]; 37 | 38 | [test setValuesForKeysWithJSONDictionary:dictionary dateFormatter:dateFormatter]; 39 | 40 | dictionary = [NSDictionary dictionaryWithObjectsAndKeys: 41 | // Use the ivar name this time instead of the property name. 42 | [NSNumber numberWithInt:27], @"string_", 43 | 44 | [NSNumber numberWithFloat:2.34], @"floatNumber", 45 | 46 | [NSNumber numberWithInt:24], @"unsignedInteger", 47 | 48 | @"2011-12-29T17:36:27", @"date", 49 | nil]; 50 | 51 | [test setValuesForKeysWithJSONDictionary:dictionary dateFormatter:dateFormatter]; 52 | 53 | } 54 | return 0; 55 | } 56 | 57 | -------------------------------------------------------------------------------- /fixpng.sh: -------------------------------------------------------------------------------- 1 | # Fix an iOS-converted PNG 2 | # By Tom Harrington, June 1 2012. 3 | 4 | fixpng () { 5 | if [ -z "$1" ]; then 6 | echo "Usage: fixpng [outputFile]" 7 | return -1 8 | else 9 | inputFile=$1 10 | 11 | # Only "png" and "PNG" are allowed 12 | pngRegex='.*.(png|PNG)$' 13 | if [[ $inputFile =~ $pngRegex ]]; then 14 | if [ -n "$2" ]; then 15 | # Use whatever name was provided 16 | outputFile=$2 17 | else 18 | # Generate a filename, preserve file extension case. 19 | extension=${BASH_REMATCH[1]} 20 | outputFile=${inputFile%.$extension}-fixed.$extension 21 | fi 22 | echo "Converting $inputFile to $outputFile" 23 | 24 | xcrun -sdk iphoneos pngcrush -q -revert-iphone-optimizations $inputFile $outputFile 25 | else 26 | echo "Skipping $inputFile since it's not a png" 27 | fi 28 | fi 29 | } 30 | 31 | # Fix a whole mess of pngs at once 32 | fixpngs () { 33 | if [ -z "$1" ]; then 34 | echo "Usage: fixpng [outputFile]" 35 | return -1 36 | else 37 | for file in "$@"; do fixpng $file; done 38 | fi 39 | 40 | } 41 | --------------------------------------------------------------------------------