├── .gitignore ├── AutozeroingArray ├── AutozeroingArray.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ └── dave.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── AutozeroingArray │ ├── AutozeroingArray-Prefix.pch │ ├── AutozeroingArray.1 │ ├── DDAutozeroingArray.h │ ├── DDAutozeroingArray.m │ └── main.m ├── DDURLBuilder ├── DDURLBuilder.h ├── DDURLBuilder.m ├── DDUrlBuilder │ ├── DDUrlBuilder.xcodeproj │ │ └── project.pbxproj │ ├── DDUrlBuilder │ │ └── DDUrlBuilder-Prefix.pch │ └── DDUrlBuilderTest │ │ ├── DDUrlBuilderTest-Info.plist │ │ ├── DDUrlBuilderTest-Prefix.pch │ │ ├── DDUrlBuilderTest.h │ │ ├── DDUrlBuilderTest.m │ │ └── en.lproj │ │ └── InfoPlist.strings └── main.m ├── DynamicStorage ├── DynamicStorage.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata └── DynamicStorage │ ├── DDDynamicStorageObject.h │ ├── DDDynamicStorageObject.m │ ├── DynamicStorage-Info.plist │ ├── DynamicStorage-Prefix.pch │ ├── DynamicStorageAppDelegate.h │ ├── DynamicStorageAppDelegate.m │ ├── DynamicStorageViewController.h │ ├── DynamicStorageViewController.m │ ├── SimpleStorage.h │ ├── SimpleStorage.m │ ├── en.lproj │ ├── DynamicStorageViewController.xib │ ├── InfoPlist.strings │ └── MainWindow.xib │ └── main.m ├── FaultingArray ├── FaultingArray.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata └── FaultingArray │ ├── DDFaultingArray.h │ ├── DDFaultingArray.m │ ├── FaultingArray-Prefix.pch │ ├── FaultingArray.1 │ └── main.m ├── GrandSuper ├── GrandSuper.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata └── GrandSuper │ ├── DDSuperProxy.h │ ├── DDSuperProxy.m │ ├── GrandSuper-Prefix.pch │ ├── GrandSuper.1 │ └── main.m ├── JoinPoints ├── JoinPoints.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata └── JoinPoints │ ├── ForwardingClass.h │ ├── ForwardingClass.m │ ├── JoinPoints-Prefix.pch │ ├── JoinPoints.1 │ ├── NSObject+JoinPoints.h │ ├── NSObject+JoinPoints.m │ └── main.m ├── OlympicRings ├── OlympicRings-Info.plist ├── OlympicRings.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── OlympicRings_Prefix.pch ├── RingLayer.h ├── RingLayer.m ├── Shared │ └── main.m ├── iPad │ ├── AppDelegate_iPad.h │ ├── AppDelegate_iPad.m │ └── MainWindow_iPad.xib └── iPhone │ ├── AppDelegate_iPhone.h │ ├── AppDelegate_iPhone.m │ └── MainWindow_iPhone.xib ├── README.markdown └── ScreenShot Detector ├── README.markdown ├── ScreenShot Detector.xcodeproj └── project.pbxproj ├── ScreenShot Detector ├── ScreenShot_Detector-Info.plist ├── ScreenShot_Detector-Prefix.pch ├── ScreenShot_DetectorAppDelegate.h ├── ScreenShot_DetectorAppDelegate.m ├── ValueTransformers.h ├── ValueTransformers.m ├── en.lproj │ ├── Credits.rtf │ ├── InfoPlist.strings │ └── MainMenu.xib └── main.m └── screenshot.png /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *xcworkspace* 3 | *xcuserdata* 4 | ._* 5 | .svn 6 | 7 | **/build 8 | **/**/*.pbxuser 9 | **/**/*.perspectivev3 10 | **/**/xcuserdata 11 | -------------------------------------------------------------------------------- /AutozeroingArray/AutozeroingArray.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 552C9CC0137B8FBE00105712 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 552C9CBF137B8FBE00105712 /* Foundation.framework */; }; 11 | 552C9CC3137B8FBE00105712 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 552C9CC2137B8FBE00105712 /* main.m */; }; 12 | 552C9CCE137B8FD400105712 /* DDAutozeroingArray.m in Sources */ = {isa = PBXBuildFile; fileRef = 552C9CCD137B8FD400105712 /* DDAutozeroingArray.m */; }; 13 | /* End PBXBuildFile section */ 14 | 15 | /* Begin PBXCopyFilesBuildPhase section */ 16 | 552C9CB9137B8FBE00105712 /* CopyFiles */ = { 17 | isa = PBXCopyFilesBuildPhase; 18 | buildActionMask = 2147483647; 19 | dstPath = /usr/share/man/man1/; 20 | dstSubfolderSpec = 0; 21 | files = ( 22 | ); 23 | runOnlyForDeploymentPostprocessing = 1; 24 | }; 25 | /* End PBXCopyFilesBuildPhase section */ 26 | 27 | /* Begin PBXFileReference section */ 28 | 552C9CBB137B8FBE00105712 /* AutozeroingArray */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = AutozeroingArray; sourceTree = BUILT_PRODUCTS_DIR; }; 29 | 552C9CBF137B8FBE00105712 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 30 | 552C9CC2137B8FBE00105712 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 31 | 552C9CC5137B8FBE00105712 /* AutozeroingArray-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AutozeroingArray-Prefix.pch"; sourceTree = ""; }; 32 | 552C9CC6137B8FBE00105712 /* AutozeroingArray.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = AutozeroingArray.1; sourceTree = ""; }; 33 | 552C9CCC137B8FD400105712 /* DDAutozeroingArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDAutozeroingArray.h; sourceTree = ""; }; 34 | 552C9CCD137B8FD400105712 /* DDAutozeroingArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDAutozeroingArray.m; sourceTree = ""; }; 35 | /* End PBXFileReference section */ 36 | 37 | /* Begin PBXFrameworksBuildPhase section */ 38 | 552C9CB8137B8FBE00105712 /* Frameworks */ = { 39 | isa = PBXFrameworksBuildPhase; 40 | buildActionMask = 2147483647; 41 | files = ( 42 | 552C9CC0137B8FBE00105712 /* Foundation.framework in Frameworks */, 43 | ); 44 | runOnlyForDeploymentPostprocessing = 0; 45 | }; 46 | /* End PBXFrameworksBuildPhase section */ 47 | 48 | /* Begin PBXGroup section */ 49 | 552C9CB0137B8FBE00105712 = { 50 | isa = PBXGroup; 51 | children = ( 52 | 552C9CC1137B8FBE00105712 /* AutozeroingArray */, 53 | 552C9CBE137B8FBE00105712 /* Frameworks */, 54 | 552C9CBC137B8FBE00105712 /* Products */, 55 | ); 56 | sourceTree = ""; 57 | }; 58 | 552C9CBC137B8FBE00105712 /* Products */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | 552C9CBB137B8FBE00105712 /* AutozeroingArray */, 62 | ); 63 | name = Products; 64 | sourceTree = ""; 65 | }; 66 | 552C9CBE137B8FBE00105712 /* Frameworks */ = { 67 | isa = PBXGroup; 68 | children = ( 69 | 552C9CBF137B8FBE00105712 /* Foundation.framework */, 70 | ); 71 | name = Frameworks; 72 | sourceTree = ""; 73 | }; 74 | 552C9CC1137B8FBE00105712 /* AutozeroingArray */ = { 75 | isa = PBXGroup; 76 | children = ( 77 | 552C9CC2137B8FBE00105712 /* main.m */, 78 | 552C9CCC137B8FD400105712 /* DDAutozeroingArray.h */, 79 | 552C9CCD137B8FD400105712 /* DDAutozeroingArray.m */, 80 | 552C9CC6137B8FBE00105712 /* AutozeroingArray.1 */, 81 | 552C9CC4137B8FBE00105712 /* Supporting Files */, 82 | ); 83 | path = AutozeroingArray; 84 | sourceTree = ""; 85 | }; 86 | 552C9CC4137B8FBE00105712 /* Supporting Files */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | 552C9CC5137B8FBE00105712 /* AutozeroingArray-Prefix.pch */, 90 | ); 91 | name = "Supporting Files"; 92 | sourceTree = ""; 93 | }; 94 | /* End PBXGroup section */ 95 | 96 | /* Begin PBXNativeTarget section */ 97 | 552C9CBA137B8FBE00105712 /* AutozeroingArray */ = { 98 | isa = PBXNativeTarget; 99 | buildConfigurationList = 552C9CC9137B8FBE00105712 /* Build configuration list for PBXNativeTarget "AutozeroingArray" */; 100 | buildPhases = ( 101 | 552C9CB7137B8FBE00105712 /* Sources */, 102 | 552C9CB8137B8FBE00105712 /* Frameworks */, 103 | 552C9CB9137B8FBE00105712 /* CopyFiles */, 104 | ); 105 | buildRules = ( 106 | ); 107 | dependencies = ( 108 | ); 109 | name = AutozeroingArray; 110 | productName = AutozeroingArray; 111 | productReference = 552C9CBB137B8FBE00105712 /* AutozeroingArray */; 112 | productType = "com.apple.product-type.tool"; 113 | }; 114 | /* End PBXNativeTarget section */ 115 | 116 | /* Begin PBXProject section */ 117 | 552C9CB2137B8FBE00105712 /* Project object */ = { 118 | isa = PBXProject; 119 | buildConfigurationList = 552C9CB5137B8FBE00105712 /* Build configuration list for PBXProject "AutozeroingArray" */; 120 | compatibilityVersion = "Xcode 3.2"; 121 | developmentRegion = English; 122 | hasScannedForEncodings = 0; 123 | knownRegions = ( 124 | en, 125 | ); 126 | mainGroup = 552C9CB0137B8FBE00105712; 127 | productRefGroup = 552C9CBC137B8FBE00105712 /* Products */; 128 | projectDirPath = ""; 129 | projectRoot = ""; 130 | targets = ( 131 | 552C9CBA137B8FBE00105712 /* AutozeroingArray */, 132 | ); 133 | }; 134 | /* End PBXProject section */ 135 | 136 | /* Begin PBXSourcesBuildPhase section */ 137 | 552C9CB7137B8FBE00105712 /* Sources */ = { 138 | isa = PBXSourcesBuildPhase; 139 | buildActionMask = 2147483647; 140 | files = ( 141 | 552C9CC3137B8FBE00105712 /* main.m in Sources */, 142 | 552C9CCE137B8FD400105712 /* DDAutozeroingArray.m in Sources */, 143 | ); 144 | runOnlyForDeploymentPostprocessing = 0; 145 | }; 146 | /* End PBXSourcesBuildPhase section */ 147 | 148 | /* Begin XCBuildConfiguration section */ 149 | 552C9CC7137B8FBE00105712 /* Debug */ = { 150 | isa = XCBuildConfiguration; 151 | buildSettings = { 152 | ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; 153 | GCC_C_LANGUAGE_STANDARD = gnu99; 154 | GCC_OPTIMIZATION_LEVEL = 0; 155 | GCC_PREPROCESSOR_DEFINITIONS = DEBUG; 156 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 157 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 158 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 159 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 160 | GCC_WARN_UNUSED_VARIABLE = YES; 161 | MACOSX_DEPLOYMENT_TARGET = 10.6; 162 | ONLY_ACTIVE_ARCH = YES; 163 | SDKROOT = macosx; 164 | }; 165 | name = Debug; 166 | }; 167 | 552C9CC8137B8FBE00105712 /* Release */ = { 168 | isa = XCBuildConfiguration; 169 | buildSettings = { 170 | ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; 171 | GCC_C_LANGUAGE_STANDARD = gnu99; 172 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 173 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 174 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 175 | GCC_WARN_UNUSED_VARIABLE = YES; 176 | MACOSX_DEPLOYMENT_TARGET = 10.6; 177 | SDKROOT = macosx; 178 | }; 179 | name = Release; 180 | }; 181 | 552C9CCA137B8FBE00105712 /* Debug */ = { 182 | isa = XCBuildConfiguration; 183 | buildSettings = { 184 | ALWAYS_SEARCH_USER_PATHS = NO; 185 | COPY_PHASE_STRIP = NO; 186 | GCC_DYNAMIC_NO_PIC = NO; 187 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 188 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 189 | GCC_PREFIX_HEADER = "AutozeroingArray/AutozeroingArray-Prefix.pch"; 190 | PRODUCT_NAME = "$(TARGET_NAME)"; 191 | }; 192 | name = Debug; 193 | }; 194 | 552C9CCB137B8FBE00105712 /* Release */ = { 195 | isa = XCBuildConfiguration; 196 | buildSettings = { 197 | ALWAYS_SEARCH_USER_PATHS = NO; 198 | COPY_PHASE_STRIP = YES; 199 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 200 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 201 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 202 | GCC_PREFIX_HEADER = "AutozeroingArray/AutozeroingArray-Prefix.pch"; 203 | PRODUCT_NAME = "$(TARGET_NAME)"; 204 | }; 205 | name = Release; 206 | }; 207 | /* End XCBuildConfiguration section */ 208 | 209 | /* Begin XCConfigurationList section */ 210 | 552C9CB5137B8FBE00105712 /* Build configuration list for PBXProject "AutozeroingArray" */ = { 211 | isa = XCConfigurationList; 212 | buildConfigurations = ( 213 | 552C9CC7137B8FBE00105712 /* Debug */, 214 | 552C9CC8137B8FBE00105712 /* Release */, 215 | ); 216 | defaultConfigurationIsVisible = 0; 217 | defaultConfigurationName = Release; 218 | }; 219 | 552C9CC9137B8FBE00105712 /* Build configuration list for PBXNativeTarget "AutozeroingArray" */ = { 220 | isa = XCConfigurationList; 221 | buildConfigurations = ( 222 | 552C9CCA137B8FBE00105712 /* Debug */, 223 | 552C9CCB137B8FBE00105712 /* Release */, 224 | ); 225 | defaultConfigurationIsVisible = 0; 226 | }; 227 | /* End XCConfigurationList section */ 228 | }; 229 | rootObject = 552C9CB2137B8FBE00105712 /* Project object */; 230 | } 231 | -------------------------------------------------------------------------------- /AutozeroingArray/AutozeroingArray.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AutozeroingArray/AutozeroingArray/AutozeroingArray-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'AutozeroingArray' target in the 'AutozeroingArray' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /AutozeroingArray/AutozeroingArray/AutozeroingArray.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 5/11/11 \" DATE 7 | .Dt AutozeroingArray 1 \" Program name and manual section number 8 | .Os Darwin 9 | .Sh NAME \" Section Header - required - don't modify 10 | .Nm AutozeroingArray, 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 -------------------------------------------------------------------------------- /AutozeroingArray/AutozeroingArray/DDAutozeroingArray.h: -------------------------------------------------------------------------------- 1 | // 2 | // DDAutozeroingArray.h 3 | // AutozeroingArray 4 | // 5 | // Created by Dave DeLong on 5/11/11. 6 | // Copyright 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DDAutozeroingArray : NSMutableArray { 12 | NSMutableArray *storage; 13 | } 14 | 15 | @end 16 | 17 | typedef NSMutableArray NSAutozeroingMutableArray; 18 | 19 | @interface NSMutableArray (DDAutozeroingArray) 20 | 21 | + (NSAutozeroingMutableArray *) autozeroingArray; 22 | + (NSAutozeroingMutableArray *) autozeroingArrayWithArray:(NSArray *)array; 23 | + (NSAutozeroingMutableArray *) autozeroingArrayWithObject:(id)object; 24 | + (NSAutozeroingMutableArray *) autozeroingArrayWithObjects:(id)object, ... NS_REQUIRES_NIL_TERMINATION; 25 | + (NSAutozeroingMutableArray *) autozeroingArrayWithObjects:(const id *)objects count:(NSUInteger)count; 26 | 27 | - (id)initAutozeroingArray; 28 | - (id)initAutozeroingArrayWithArray:(NSArray *)array; 29 | - (id)initAutozeroingArrayWithObject:(id)object; 30 | - (id)initAutozeroingArrayWithObjects:(id)object, ... NS_REQUIRES_NIL_TERMINATION; 31 | - (id)initAutozeroingArrayWithObjects:(const id *)objects count:(NSUInteger)count; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /AutozeroingArray/AutozeroingArray/DDAutozeroingArray.m: -------------------------------------------------------------------------------- 1 | // 2 | // DDAutozeroingArray.m 3 | // AutozeroingArray 4 | // 5 | // Created by Dave DeLong on 5/11/11. 6 | // Copyright 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "DDAutozeroingArray.h" 10 | #import 11 | 12 | static char DDAutozeroingObserverKey = 1; 13 | static NSString *DDAutozeroingObjectDidDeallocateNotification = @"DDAutozeroingObjectDidDeallocateNotification"; 14 | 15 | //this is an object that gets attached to an object in an AutozeroingArray 16 | //when the attachee is deallocated/finalized, the associated objects are also cleaned up 17 | //this causes the DeallocationObserver to be released (and deallocated/finalized) 18 | //and when that happens, it posts an "object did deallocate" notification 19 | //the object pointer (now stale) is posted in the notification, wrapped in an NSValue 20 | @interface DDAutozeroingArrayDeallocationObserver : NSObject { 21 | @private 22 | NSValue *objectWrapper; 23 | } 24 | @property (readonly) NSValue *objectWrapper; 25 | - (id)initWithObject:(id)anObject; 26 | @end 27 | 28 | @implementation DDAutozeroingArrayDeallocationObserver 29 | @synthesize objectWrapper; 30 | 31 | - (id)initWithObject:(id)anObject { 32 | self = [super init]; 33 | if (self) { 34 | objectWrapper = [[NSValue valueWithNonretainedObject:anObject] retain]; 35 | } 36 | return self; 37 | } 38 | 39 | - (void)finalize { 40 | [[NSNotificationCenter defaultCenter] postNotificationName:DDAutozeroingObjectDidDeallocateNotification object:self userInfo:nil]; 41 | [super finalize]; 42 | } 43 | 44 | - (void)dealloc { 45 | [[NSNotificationCenter defaultCenter] postNotificationName:DDAutozeroingObjectDidDeallocateNotification object:self userInfo:nil]; 46 | [objectWrapper release]; 47 | [super dealloc]; 48 | } 49 | 50 | @end 51 | 52 | @implementation DDAutozeroingArray 53 | 54 | - (id)initWithObjects:(const id *)objects count:(NSUInteger)cnt { 55 | self = [self init]; 56 | if (self) { 57 | CFArrayCallBacks callbacks = kCFTypeArrayCallBacks; 58 | callbacks.retain = NULL; 59 | callbacks.release = NULL; 60 | storage = (NSMutableArray *)CFArrayCreateMutable(NULL, 0, &callbacks); 61 | 62 | for (NSUInteger i = 0; i < cnt; ++i) { 63 | id object = objects[i]; 64 | [self addObject:object]; 65 | } 66 | } 67 | return self; 68 | } 69 | 70 | #pragma mark Memory Management 71 | 72 | - (void)finalize { 73 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 74 | [super finalize]; 75 | } 76 | 77 | - (void)dealloc { 78 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 79 | [storage release]; 80 | [super dealloc]; 81 | } 82 | 83 | #pragma mark Autozeroing 84 | 85 | - (void)observeObject:(id)anObject { 86 | id observer = objc_getAssociatedObject(anObject, &DDAutozeroingObserverKey); 87 | if (observer == nil) { 88 | observer = [[DDAutozeroingArrayDeallocationObserver alloc] initWithObject:anObject]; 89 | objc_setAssociatedObject(anObject, &DDAutozeroingObserverKey, observer, OBJC_ASSOCIATION_RETAIN); 90 | 91 | [[NSNotificationCenter defaultCenter] addObserver:self 92 | selector:@selector(objectDeallocated:) 93 | name:DDAutozeroingObjectDidDeallocateNotification 94 | object:observer]; 95 | [observer release]; 96 | } 97 | 98 | } 99 | 100 | - (void)stopObservingObject:(id)anObject { 101 | [[NSNotificationCenter defaultCenter] removeObserver:self name:DDAutozeroingObjectDidDeallocateNotification object:anObject]; 102 | } 103 | 104 | - (void)objectDeallocated:(NSNotification *)note { 105 | NSValue *wrapper = [[note object] objectWrapper]; 106 | id pointer = [wrapper nonretainedObjectValue]; 107 | [storage removeObject:pointer]; 108 | } 109 | 110 | #pragma mark NS(Mutable)Array overrides 111 | 112 | - (NSUInteger)count { 113 | return [storage count]; 114 | } 115 | 116 | - (id)objectAtIndex:(NSUInteger)index { 117 | return [storage objectAtIndex:index]; 118 | } 119 | 120 | - (void)insertObject:(id)anObject atIndex:(NSUInteger)index { 121 | [self observeObject:anObject]; 122 | [storage insertObject:anObject atIndex:index]; 123 | } 124 | 125 | - (void)removeObjectAtIndex:(NSUInteger)index { 126 | [self stopObservingObject:[self objectAtIndex:index]]; 127 | [storage removeObjectAtIndex:index]; 128 | } 129 | 130 | - (void)addObject:(id)anObject { 131 | [self observeObject:anObject]; 132 | [storage addObject:anObject]; 133 | } 134 | 135 | - (void)removeLastObject { 136 | [self stopObservingObject:[self lastObject]]; 137 | [storage removeLastObject]; 138 | } 139 | 140 | - (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject { 141 | [self stopObservingObject:[self objectAtIndex:index]]; 142 | [self observeObject:anObject]; 143 | [storage replaceObjectAtIndex:index withObject:anObject]; 144 | } 145 | 146 | - (NSString *)description { 147 | return [storage description]; 148 | } 149 | 150 | - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len { 151 | return [storage countByEnumeratingWithState:state objects:stackbuf count:len]; 152 | } 153 | 154 | @end 155 | 156 | #pragma mark - 157 | #pragma mark NSMutableArray (DDAutozeroingArray) 158 | 159 | const void* DDAutozeroingArrayRetainCallback(CFAllocatorRef allocator, const void *value) { 160 | id object = (id)value; 161 | 162 | id observer = objc_getAssociatedObject(object, &DDAutozeroingObserverKey); 163 | if (observer == nil) { 164 | observer = [[DDAutozeroingArrayDeallocationObserver alloc] initWithObject:object]; 165 | objc_setAssociatedObject(object, &DDAutozeroingObserverKey, observer, OBJC_ASSOCIATION_RETAIN); 166 | [observer release]; 167 | } 168 | 169 | return value; 170 | } 171 | 172 | @implementation NSMutableArray (DDAutozeroingArray) 173 | 174 | + (NSAutozeroingMutableArray *) autozeroingArray { 175 | return [[[self alloc] initAutozeroingArray] autorelease]; 176 | } 177 | 178 | + (NSAutozeroingMutableArray *) autozeroingArrayWithArray:(NSArray *)array { 179 | return [[[self alloc] initAutozeroingArrayWithArray:array] autorelease]; 180 | } 181 | 182 | + (NSAutozeroingMutableArray *) autozeroingArrayWithObject:(id)object { 183 | return [[[self alloc] initAutozeroingArrayWithObject:object] autorelease]; 184 | } 185 | 186 | + (NSAutozeroingMutableArray *) autozeroingArrayWithObjects:(id)object, ... { 187 | if (object == nil) { 188 | return [self autozeroingArray]; 189 | } 190 | 191 | NSMutableArray *tmp = [[NSMutableArray alloc] init]; 192 | va_list args; 193 | va_start(args, object); 194 | while (object != nil) { 195 | [tmp addObject:object]; 196 | object = va_arg(args, id); 197 | } 198 | va_end(args); 199 | NSAutozeroingMutableArray *array = [self autozeroingArrayWithArray:tmp]; 200 | [tmp release]; 201 | 202 | return array; 203 | } 204 | 205 | + (NSAutozeroingMutableArray *) autozeroingArrayWithObjects:(const id *)objects count:(NSUInteger)count { 206 | return [[[self alloc] initAutozeroingArrayWithObjects:objects count:count] autorelease]; 207 | } 208 | 209 | - (id)initAutozeroingArray { 210 | return [self initAutozeroingArrayWithObjects:NULL count:0]; 211 | } 212 | 213 | - (id)initAutozeroingArrayWithArray:(NSArray *)array { 214 | id *objects = calloc(sizeof(id), [array count]); 215 | [array getObjects:objects range:NSMakeRange(0, [array count])]; 216 | 217 | self = [self initAutozeroingArrayWithObjects:objects count:[array count]]; 218 | free(objects); 219 | return self; 220 | } 221 | 222 | - (id)initAutozeroingArrayWithObject:(id)object { 223 | return [self initAutozeroingArrayWithObjects:&object count:1]; 224 | } 225 | 226 | - (id)initAutozeroingArrayWithObjects:(id)object, ... { 227 | if (object == nil) { 228 | return [self initAutozeroingArray]; 229 | } 230 | 231 | NSMutableArray *tmp = [[NSMutableArray alloc] init]; 232 | va_list args; 233 | va_start(args, object); 234 | while (object != nil) { 235 | [tmp addObject:object]; 236 | object = va_arg(args, id); 237 | } 238 | va_end(args); 239 | self = [self initAutozeroingArrayWithArray:tmp]; 240 | [tmp release]; 241 | 242 | return self; 243 | } 244 | 245 | // designated initializer for this category 246 | - (id)initAutozeroingArrayWithObjects:(const id *)objects count:(NSUInteger)count { 247 | [self release]; 248 | 249 | CFArrayCallBacks callbacks = kCFTypeArrayCallBacks; 250 | callbacks.retain = &DDAutozeroingArrayRetainCallback; 251 | callbacks.release = NULL; 252 | 253 | // the magic of Toll-Free Bridging 254 | self = (NSAutozeroingMutableArray *)CFArrayCreateMutable(NULL, count, &callbacks); 255 | 256 | for (NSUInteger i = 0; i < count; ++i) { 257 | [self addObject:objects[i]]; 258 | } 259 | 260 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_ddautozeroingarray_objectDeallocated:) name:DDAutozeroingObjectDidDeallocateNotification object:nil]; 261 | 262 | return self; 263 | } 264 | 265 | - (void)_ddautozeroingarray_objectDeallocated:(NSNotification *)note { 266 | NSValue *wrapper = [[note object] objectWrapper]; 267 | id pointer = [wrapper nonretainedObjectValue]; 268 | [self removeObject:pointer]; 269 | } 270 | 271 | @end 272 | -------------------------------------------------------------------------------- /AutozeroingArray/AutozeroingArray/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // AutozeroingArray 4 | // 5 | // Created by Dave DeLong on 5/11/11. 6 | // Copyright 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "DDAutozeroingArray.h" 11 | 12 | id object = nil; 13 | 14 | int main (int argc, const char * argv[]) 15 | { 16 | 17 | NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 18 | 19 | /** 20 | This shows that the array will automatically zero out items when they're deallocated via an ARP 21 | */ 22 | NSAutoreleasePool *inner = [[NSAutoreleasePool alloc] init]; 23 | NSMutableArray *tmp = [NSMutableArray array]; 24 | for (int i = 0; i < 100; ++i) { 25 | [tmp addObject:[NSString stringWithFormat:@"string #%d", i+1]]; 26 | } 27 | DDAutozeroingArray *arrayWithArray = [[DDAutozeroingArray alloc] initWithArray:tmp]; 28 | NSLog(@"%@", arrayWithArray); 29 | [inner drain]; 30 | NSLog(@"%@", arrayWithArray); 31 | [arrayWithArray release]; 32 | 33 | /** 34 | This shows that the array will automatically zero out items when they're explicitly released 35 | */ 36 | DDAutozeroingArray *array = [DDAutozeroingArray array]; 37 | NSObject *o = [[NSObject alloc] init]; 38 | [array addObject:o]; 39 | NSLog(@"%@", array); 40 | [o release]; 41 | NSLog(@"%@", array); 42 | 43 | /** 44 | This shows a true NSMutableArray that auto-zeros its objects 45 | */ 46 | NSAutozeroingMutableArray *mArray = [NSMutableArray autozeroingArray]; 47 | o = [[NSObject alloc] init]; 48 | [mArray addObject:o]; 49 | NSLog(@"%@", mArray); 50 | [o release]; 51 | NSLog(@"%@", mArray); 52 | 53 | [pool drain]; 54 | return 0; 55 | } 56 | 57 | -------------------------------------------------------------------------------- /DDURLBuilder/DDURLBuilder.h: -------------------------------------------------------------------------------- 1 | // 2 | // DDURLBuilder.h 3 | // EmptyFoundation 4 | // 5 | // Created by Dave DeLong on 2/17/11. 6 | // Copyright 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface DDURLBuilder : NSObject { 13 | @private 14 | 15 | NSString *scheme; 16 | NSString *user; 17 | NSString *password; 18 | NSString *host; 19 | NSNumber *port; 20 | NSString *path; 21 | NSMutableDictionary *queryValues; 22 | NSString *fragment; 23 | } 24 | 25 | + (id) URLBuilderWithURL:(NSURL *)url; 26 | - (id) initWithURL:(NSURL *)url; 27 | 28 | @property (nonatomic, retain) NSURL *URL; 29 | 30 | @property (nonatomic, retain) NSString *scheme; 31 | @property (nonatomic, retain) NSString *user; 32 | @property (nonatomic, retain) NSString *password; 33 | @property (nonatomic, retain) NSString *host; 34 | @property (nonatomic, retain) NSNumber *port; 35 | @property (nonatomic, retain) NSString *path; 36 | @property (nonatomic, retain) NSString *fragment; 37 | 38 | @property (nonatomic, assign) BOOL usesSchemeSeparators; 39 | 40 | - (NSArray *) queryValuesForKey:(NSString *)key; 41 | - (void) addQueryValue:(NSString *)value forKey:(NSString *)key; 42 | - (void) removeQueryValue:(NSString *)value forKey:(NSString *)key; 43 | - (void) removeQueryValuesForKey:(NSString *)key; 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /DDURLBuilder/DDURLBuilder.m: -------------------------------------------------------------------------------- 1 | // 2 | // DDURLBuilder.m 3 | // EmptyFoundation 4 | // 5 | // Created by Dave DeLong on 2/17/11. 6 | // Copyright 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "DDURLBuilder.h" 10 | 11 | NSString *ddurlbuilder_percentEncode(NSString *string) { 12 | NSMutableString * output = [NSMutableString string]; 13 | const unsigned char * source = (const unsigned char *)[string UTF8String]; 14 | size_t sourceLen = strlen((const char *)source); 15 | for (size_t i = 0; i < sourceLen; ++i) { 16 | const unsigned char thisChar = source[i]; 17 | if (thisChar == ' '){ 18 | [output appendString:@"+"]; 19 | } else if (thisChar == '.' || thisChar == '-' || thisChar == '_' || thisChar == '~' || 20 | (thisChar >= 'a' && thisChar <= 'z') || 21 | (thisChar >= 'A' && thisChar <= 'Z') || 22 | (thisChar >= '0' && thisChar <= '9')) { 23 | [output appendFormat:@"%c", thisChar]; 24 | } else { 25 | [output appendFormat:@"%%%02X", thisChar]; 26 | } 27 | } 28 | return output; 29 | } 30 | 31 | @implementation DDURLBuilder 32 | 33 | @synthesize scheme; 34 | @synthesize user; 35 | @synthesize password; 36 | @synthesize host; 37 | @synthesize path; 38 | @synthesize fragment; 39 | @synthesize port; 40 | 41 | @synthesize usesSchemeSeparators; 42 | 43 | + (id) URLBuilderWithURL:(NSURL *)url { 44 | return [[[self alloc] initWithURL:url] autorelease]; 45 | } 46 | 47 | - (id) initWithURL:(NSURL *)url { 48 | self = [super init]; 49 | if (self) { 50 | queryValues = [[NSMutableDictionary alloc] init]; 51 | [self setUsesSchemeSeparators:YES]; 52 | if (url) { 53 | [self setURL:url]; 54 | } 55 | } 56 | return self; 57 | } 58 | 59 | - (void)dealloc { 60 | [scheme release]; 61 | [user release]; 62 | [password release]; 63 | [host release]; 64 | [port release]; 65 | [path release]; 66 | [queryValues release]; 67 | [fragment release]; 68 | [super dealloc]; 69 | } 70 | 71 | - (void) setURL:(NSURL *)URL { 72 | [self setScheme:[URL scheme]]; 73 | [self setUser:[URL user]]; 74 | [self setPassword:[URL password]]; 75 | [self setPath:[URL path]]; 76 | [self setHost:[URL host]]; 77 | [self setFragment:[URL fragment]]; 78 | [self setPort:[URL port]]; 79 | 80 | NSString *absolute = [URL absoluteString]; 81 | [self setUsesSchemeSeparators:([absolute hasPrefix:[NSString stringWithFormat:@"%@://", [self scheme]]])]; 82 | 83 | [queryValues removeAllObjects]; 84 | NSString *query = [URL query]; 85 | NSArray *components = [query componentsSeparatedByString:@"&"]; 86 | for (NSString *component in components) { 87 | NSArray *bits = [component componentsSeparatedByString:@"="]; 88 | if ([bits count] != 2) { 89 | NSLog(@"illegal query string component: %@", component); 90 | continue; 91 | } 92 | 93 | NSString *key = [[bits objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 94 | NSString *value = [[bits objectAtIndex:1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 95 | [self addQueryValue:value forKey:key]; 96 | } 97 | } 98 | 99 | - (NSURL *)URL { 100 | if ([self scheme] == nil || [self host] == nil) { return nil; } 101 | 102 | NSMutableString *url = [NSMutableString string]; 103 | 104 | [url appendFormat:@"%@:", [self scheme]]; 105 | if ([self usesSchemeSeparators]) { 106 | [url appendString:@"//"]; 107 | } 108 | if ([self user]) { 109 | [url appendString:ddurlbuilder_percentEncode([self user])]; 110 | if ([self password]) { 111 | [url appendFormat:@":%@", ddurlbuilder_percentEncode([self password])]; 112 | } 113 | [url appendString:@"@"]; 114 | } 115 | 116 | [url appendString:ddurlbuilder_percentEncode([self host])]; 117 | if ([self port]) { 118 | [url appendFormat:@":%@", [self port]]; 119 | } 120 | 121 | 122 | if ([self path]) { 123 | NSArray *pathComponents = [[self path] pathComponents]; 124 | for (NSString *component in pathComponents) { 125 | if ([component isEqualToString:@"/"]) { continue; } 126 | [url appendFormat:@"/%@", ddurlbuilder_percentEncode(component)]; 127 | } 128 | } 129 | 130 | if ([queryValues count] > 0) { 131 | NSMutableArray *components = [NSMutableArray array]; 132 | for (NSString *key in queryValues) { 133 | NSArray *values = [queryValues objectForKey:key]; 134 | key = ddurlbuilder_percentEncode(key); 135 | for (NSString *value in values) { 136 | value = ddurlbuilder_percentEncode(value); 137 | NSString *component = [NSString stringWithFormat:@"%@=%@", key, value]; 138 | [components addObject:component]; 139 | } 140 | } 141 | NSString *queryString = [components componentsJoinedByString:@"&"]; 142 | [url appendFormat:@"?%@", queryString]; 143 | } 144 | 145 | if ([self fragment]) { 146 | [url appendFormat:@"#%@", [self fragment]]; 147 | } 148 | 149 | return [NSURL URLWithString:url]; 150 | } 151 | 152 | - (NSArray *) queryValuesForKey:(NSString *)key { 153 | if (key == nil) { return nil; } 154 | return [[[queryValues objectForKey:key] copy] autorelease]; 155 | } 156 | 157 | - (void) addQueryValue:(NSString *)value forKey:(NSString *)key { 158 | if (value == nil || key == nil) { return; } 159 | NSMutableArray *values = [queryValues objectForKey:key]; 160 | if (values == nil) { 161 | values = [NSMutableArray array]; 162 | [queryValues setObject:values forKey:key]; 163 | } 164 | [values addObject:value]; 165 | } 166 | 167 | - (void) removeQueryValue:(NSString *)value forKey:(NSString *)key { 168 | if (value == nil || key == nil) { return; } 169 | NSMutableArray *values = [queryValues objectForKey:key]; 170 | if (values) { 171 | [values removeObject:value]; 172 | } 173 | } 174 | 175 | - (void) removeQueryValuesForKey:(NSString *)key { 176 | if (key == nil) { return; } 177 | [queryValues removeObjectForKey:key]; 178 | } 179 | 180 | @end 181 | -------------------------------------------------------------------------------- /DDURLBuilder/DDUrlBuilder/DDUrlBuilder/DDUrlBuilder-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'DDUrlBuilder' target in the 'DDUrlBuilder' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /DDURLBuilder/DDUrlBuilder/DDUrlBuilderTest/DDUrlBuilderTest-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | org.EmbeddedSources.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /DDURLBuilder/DDUrlBuilder/DDUrlBuilderTest/DDUrlBuilderTest-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'DDUrlBuilderTest' target in the 'DDUrlBuilderTest' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #import 8 | #endif 9 | -------------------------------------------------------------------------------- /DDURLBuilder/DDUrlBuilder/DDUrlBuilderTest/DDUrlBuilderTest.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface DDUrlBuilderTest : SenTestCase 4 | 5 | @end 6 | -------------------------------------------------------------------------------- /DDURLBuilder/DDUrlBuilder/DDUrlBuilderTest/DDUrlBuilderTest.m: -------------------------------------------------------------------------------- 1 | #import "DDUrlBuilderTest.h" 2 | #import "DDURLBuilder.h" 3 | 4 | @implementation DDUrlBuilderTest 5 | 6 | -(void)testAuthorExample 7 | { 8 | 9 | NSURL* expected_ = [ NSURL URLWithString: @"http://www.google.com/search?client=safari&rls=en&q=what+is+the+answer+to+the+ultimate+question+of+life+the+universe+and+everything&ie=UTF-8&oe=UTF-8" ]; 10 | 11 | DDURLBuilder *builder = [DDURLBuilder URLBuilderWithURL:nil]; 12 | [builder setHost:@"google.com"]; 13 | [builder setScheme:@"http"]; 14 | [builder setPath:@"search"]; 15 | [builder addQueryValue:@"safari" forKey:@"client"]; 16 | [builder addQueryValue:@"en" forKey:@"rls"]; 17 | [builder addQueryValue:@"what is the answer to the ultimate question of life the universe and everything" forKey:@"q"]; 18 | [builder addQueryValue:@"UTF-8" forKey:@"ie"]; 19 | [builder addQueryValue:@"UTF-8" forKey:@"oe"]; 20 | 21 | NSURL* received_ = [ builder URL ]; 22 | 23 | STAssertTrue( [ expected_ isEqual: received_ ], @"result URL mismatch" ); 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /DDURLBuilder/DDUrlBuilder/DDUrlBuilderTest/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /DDURLBuilder/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import "DDURLBuilder.h" 3 | 4 | int main (int argc, const char * argv[]) { 5 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 6 | 7 | // http://www.google.com/search?client=safari&rls=en&q=what+is+the+answer+to+the+ultimate+question+of+life+the+universe+and+everything&ie=UTF-8&oe=UTF-8 8 | 9 | DDURLBuilder *builder = [DDURLBuilder URLBuilderWithURL:nil]; 10 | [builder setHost:@"google.com"]; 11 | [builder setScheme:@"http"]; 12 | [builder setPath:@"search"]; 13 | [builder addQueryValue:@"safari" forKey:@"client"]; 14 | [builder addQueryValue:@"en" forKey:@"rls"]; 15 | [builder addQueryValue:@"what is the answer to the ultimate question of life the universe and everything" forKey:@"q"]; 16 | [builder addQueryValue:@"UTF-8" forKey:@"ie"]; 17 | [builder addQueryValue:@"UTF-8" forKey:@"oe"]; 18 | 19 | NSLog(@"%@", [builder URL]); 20 | 21 | [pool drain]; 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /DynamicStorage/DynamicStorage.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 559E46F11370F6E400FEC4E5 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 559E46F01370F6E400FEC4E5 /* UIKit.framework */; }; 11 | 559E46F31370F6E400FEC4E5 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 559E46F21370F6E400FEC4E5 /* Foundation.framework */; }; 12 | 559E46F51370F6E400FEC4E5 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 559E46F41370F6E400FEC4E5 /* CoreGraphics.framework */; }; 13 | 559E46FB1370F6E400FEC4E5 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 559E46F91370F6E400FEC4E5 /* InfoPlist.strings */; }; 14 | 559E46FE1370F6E400FEC4E5 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 559E46FD1370F6E400FEC4E5 /* main.m */; }; 15 | 559E47011370F6E400FEC4E5 /* DynamicStorageAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 559E47001370F6E400FEC4E5 /* DynamicStorageAppDelegate.m */; }; 16 | 559E47041370F6E400FEC4E5 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 559E47021370F6E400FEC4E5 /* MainWindow.xib */; }; 17 | 559E47071370F6E400FEC4E5 /* DynamicStorageViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 559E47061370F6E400FEC4E5 /* DynamicStorageViewController.m */; }; 18 | 559E470A1370F6E400FEC4E5 /* DynamicStorageViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 559E47081370F6E400FEC4E5 /* DynamicStorageViewController.xib */; }; 19 | 559E47121370F70800FEC4E5 /* DDDynamicStorageObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 559E47111370F70800FEC4E5 /* DDDynamicStorageObject.m */; }; 20 | 559E47151370F7A900FEC4E5 /* SimpleStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = 559E47141370F7A900FEC4E5 /* SimpleStorage.m */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXFileReference section */ 24 | 559E46EC1370F6E400FEC4E5 /* DynamicStorage.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DynamicStorage.app; sourceTree = BUILT_PRODUCTS_DIR; }; 25 | 559E46F01370F6E400FEC4E5 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 26 | 559E46F21370F6E400FEC4E5 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 27 | 559E46F41370F6E400FEC4E5 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 28 | 559E46F81370F6E400FEC4E5 /* DynamicStorage-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "DynamicStorage-Info.plist"; sourceTree = ""; }; 29 | 559E46FA1370F6E400FEC4E5 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 30 | 559E46FC1370F6E400FEC4E5 /* DynamicStorage-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "DynamicStorage-Prefix.pch"; sourceTree = ""; }; 31 | 559E46FD1370F6E400FEC4E5 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 32 | 559E46FF1370F6E400FEC4E5 /* DynamicStorageAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DynamicStorageAppDelegate.h; sourceTree = ""; }; 33 | 559E47001370F6E400FEC4E5 /* DynamicStorageAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DynamicStorageAppDelegate.m; sourceTree = ""; }; 34 | 559E47031370F6E400FEC4E5 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainWindow.xib; sourceTree = ""; }; 35 | 559E47051370F6E400FEC4E5 /* DynamicStorageViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DynamicStorageViewController.h; sourceTree = ""; }; 36 | 559E47061370F6E400FEC4E5 /* DynamicStorageViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DynamicStorageViewController.m; sourceTree = ""; }; 37 | 559E47091370F6E400FEC4E5 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/DynamicStorageViewController.xib; sourceTree = ""; }; 38 | 559E47101370F70800FEC4E5 /* DDDynamicStorageObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDDynamicStorageObject.h; sourceTree = ""; }; 39 | 559E47111370F70800FEC4E5 /* DDDynamicStorageObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDDynamicStorageObject.m; sourceTree = ""; }; 40 | 559E47131370F7A900FEC4E5 /* SimpleStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimpleStorage.h; sourceTree = ""; }; 41 | 559E47141370F7A900FEC4E5 /* SimpleStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SimpleStorage.m; sourceTree = ""; }; 42 | /* End PBXFileReference section */ 43 | 44 | /* Begin PBXFrameworksBuildPhase section */ 45 | 559E46E91370F6E400FEC4E5 /* Frameworks */ = { 46 | isa = PBXFrameworksBuildPhase; 47 | buildActionMask = 2147483647; 48 | files = ( 49 | 559E46F11370F6E400FEC4E5 /* UIKit.framework in Frameworks */, 50 | 559E46F31370F6E400FEC4E5 /* Foundation.framework in Frameworks */, 51 | 559E46F51370F6E400FEC4E5 /* CoreGraphics.framework in Frameworks */, 52 | ); 53 | runOnlyForDeploymentPostprocessing = 0; 54 | }; 55 | /* End PBXFrameworksBuildPhase section */ 56 | 57 | /* Begin PBXGroup section */ 58 | 559E46E11370F6E400FEC4E5 = { 59 | isa = PBXGroup; 60 | children = ( 61 | 559E46F61370F6E400FEC4E5 /* DynamicStorage */, 62 | 559E46EF1370F6E400FEC4E5 /* Frameworks */, 63 | 559E46ED1370F6E400FEC4E5 /* Products */, 64 | ); 65 | sourceTree = ""; 66 | }; 67 | 559E46ED1370F6E400FEC4E5 /* Products */ = { 68 | isa = PBXGroup; 69 | children = ( 70 | 559E46EC1370F6E400FEC4E5 /* DynamicStorage.app */, 71 | ); 72 | name = Products; 73 | sourceTree = ""; 74 | }; 75 | 559E46EF1370F6E400FEC4E5 /* Frameworks */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | 559E46F01370F6E400FEC4E5 /* UIKit.framework */, 79 | 559E46F21370F6E400FEC4E5 /* Foundation.framework */, 80 | 559E46F41370F6E400FEC4E5 /* CoreGraphics.framework */, 81 | ); 82 | name = Frameworks; 83 | sourceTree = ""; 84 | }; 85 | 559E46F61370F6E400FEC4E5 /* DynamicStorage */ = { 86 | isa = PBXGroup; 87 | children = ( 88 | 559E46FF1370F6E400FEC4E5 /* DynamicStorageAppDelegate.h */, 89 | 559E47001370F6E400FEC4E5 /* DynamicStorageAppDelegate.m */, 90 | 559E47021370F6E400FEC4E5 /* MainWindow.xib */, 91 | 559E47051370F6E400FEC4E5 /* DynamicStorageViewController.h */, 92 | 559E47061370F6E400FEC4E5 /* DynamicStorageViewController.m */, 93 | 559E47081370F6E400FEC4E5 /* DynamicStorageViewController.xib */, 94 | 559E47101370F70800FEC4E5 /* DDDynamicStorageObject.h */, 95 | 559E47111370F70800FEC4E5 /* DDDynamicStorageObject.m */, 96 | 559E47131370F7A900FEC4E5 /* SimpleStorage.h */, 97 | 559E47141370F7A900FEC4E5 /* SimpleStorage.m */, 98 | 559E46F71370F6E400FEC4E5 /* Supporting Files */, 99 | ); 100 | path = DynamicStorage; 101 | sourceTree = ""; 102 | }; 103 | 559E46F71370F6E400FEC4E5 /* Supporting Files */ = { 104 | isa = PBXGroup; 105 | children = ( 106 | 559E46F81370F6E400FEC4E5 /* DynamicStorage-Info.plist */, 107 | 559E46F91370F6E400FEC4E5 /* InfoPlist.strings */, 108 | 559E46FC1370F6E400FEC4E5 /* DynamicStorage-Prefix.pch */, 109 | 559E46FD1370F6E400FEC4E5 /* main.m */, 110 | ); 111 | name = "Supporting Files"; 112 | sourceTree = ""; 113 | }; 114 | /* End PBXGroup section */ 115 | 116 | /* Begin PBXNativeTarget section */ 117 | 559E46EB1370F6E400FEC4E5 /* DynamicStorage */ = { 118 | isa = PBXNativeTarget; 119 | buildConfigurationList = 559E470D1370F6E400FEC4E5 /* Build configuration list for PBXNativeTarget "DynamicStorage" */; 120 | buildPhases = ( 121 | 559E46E81370F6E400FEC4E5 /* Sources */, 122 | 559E46E91370F6E400FEC4E5 /* Frameworks */, 123 | 559E46EA1370F6E400FEC4E5 /* Resources */, 124 | ); 125 | buildRules = ( 126 | ); 127 | dependencies = ( 128 | ); 129 | name = DynamicStorage; 130 | productName = DynamicStorage; 131 | productReference = 559E46EC1370F6E400FEC4E5 /* DynamicStorage.app */; 132 | productType = "com.apple.product-type.application"; 133 | }; 134 | /* End PBXNativeTarget section */ 135 | 136 | /* Begin PBXProject section */ 137 | 559E46E31370F6E400FEC4E5 /* Project object */ = { 138 | isa = PBXProject; 139 | buildConfigurationList = 559E46E61370F6E400FEC4E5 /* Build configuration list for PBXProject "DynamicStorage" */; 140 | compatibilityVersion = "Xcode 3.2"; 141 | developmentRegion = English; 142 | hasScannedForEncodings = 0; 143 | knownRegions = ( 144 | en, 145 | ); 146 | mainGroup = 559E46E11370F6E400FEC4E5; 147 | productRefGroup = 559E46ED1370F6E400FEC4E5 /* Products */; 148 | projectDirPath = ""; 149 | projectRoot = ""; 150 | targets = ( 151 | 559E46EB1370F6E400FEC4E5 /* DynamicStorage */, 152 | ); 153 | }; 154 | /* End PBXProject section */ 155 | 156 | /* Begin PBXResourcesBuildPhase section */ 157 | 559E46EA1370F6E400FEC4E5 /* Resources */ = { 158 | isa = PBXResourcesBuildPhase; 159 | buildActionMask = 2147483647; 160 | files = ( 161 | 559E46FB1370F6E400FEC4E5 /* InfoPlist.strings in Resources */, 162 | 559E47041370F6E400FEC4E5 /* MainWindow.xib in Resources */, 163 | 559E470A1370F6E400FEC4E5 /* DynamicStorageViewController.xib in Resources */, 164 | ); 165 | runOnlyForDeploymentPostprocessing = 0; 166 | }; 167 | /* End PBXResourcesBuildPhase section */ 168 | 169 | /* Begin PBXSourcesBuildPhase section */ 170 | 559E46E81370F6E400FEC4E5 /* Sources */ = { 171 | isa = PBXSourcesBuildPhase; 172 | buildActionMask = 2147483647; 173 | files = ( 174 | 559E46FE1370F6E400FEC4E5 /* main.m in Sources */, 175 | 559E47011370F6E400FEC4E5 /* DynamicStorageAppDelegate.m in Sources */, 176 | 559E47071370F6E400FEC4E5 /* DynamicStorageViewController.m in Sources */, 177 | 559E47121370F70800FEC4E5 /* DDDynamicStorageObject.m in Sources */, 178 | 559E47151370F7A900FEC4E5 /* SimpleStorage.m in Sources */, 179 | ); 180 | runOnlyForDeploymentPostprocessing = 0; 181 | }; 182 | /* End PBXSourcesBuildPhase section */ 183 | 184 | /* Begin PBXVariantGroup section */ 185 | 559E46F91370F6E400FEC4E5 /* InfoPlist.strings */ = { 186 | isa = PBXVariantGroup; 187 | children = ( 188 | 559E46FA1370F6E400FEC4E5 /* en */, 189 | ); 190 | name = InfoPlist.strings; 191 | sourceTree = ""; 192 | }; 193 | 559E47021370F6E400FEC4E5 /* MainWindow.xib */ = { 194 | isa = PBXVariantGroup; 195 | children = ( 196 | 559E47031370F6E400FEC4E5 /* en */, 197 | ); 198 | name = MainWindow.xib; 199 | sourceTree = ""; 200 | }; 201 | 559E47081370F6E400FEC4E5 /* DynamicStorageViewController.xib */ = { 202 | isa = PBXVariantGroup; 203 | children = ( 204 | 559E47091370F6E400FEC4E5 /* en */, 205 | ); 206 | name = DynamicStorageViewController.xib; 207 | sourceTree = ""; 208 | }; 209 | /* End PBXVariantGroup section */ 210 | 211 | /* Begin XCBuildConfiguration section */ 212 | 559E470B1370F6E400FEC4E5 /* Debug */ = { 213 | isa = XCBuildConfiguration; 214 | buildSettings = { 215 | ARCHS = "$(ARCHS_UNIVERSAL_IPHONE_OS)"; 216 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 217 | GCC_C_LANGUAGE_STANDARD = gnu99; 218 | GCC_OPTIMIZATION_LEVEL = 0; 219 | GCC_PREPROCESSOR_DEFINITIONS = DEBUG; 220 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 221 | GCC_VERSION = com.apple.compilers.llvmgcc42; 222 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 223 | GCC_WARN_UNUSED_VARIABLE = YES; 224 | IPHONEOS_DEPLOYMENT_TARGET = 4.3; 225 | SDKROOT = iphoneos; 226 | TARGETED_DEVICE_FAMILY = 2; 227 | }; 228 | name = Debug; 229 | }; 230 | 559E470C1370F6E400FEC4E5 /* Release */ = { 231 | isa = XCBuildConfiguration; 232 | buildSettings = { 233 | ARCHS = "$(ARCHS_UNIVERSAL_IPHONE_OS)"; 234 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 235 | GCC_C_LANGUAGE_STANDARD = gnu99; 236 | GCC_VERSION = com.apple.compilers.llvmgcc42; 237 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 238 | GCC_WARN_UNUSED_VARIABLE = YES; 239 | IPHONEOS_DEPLOYMENT_TARGET = 4.3; 240 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 241 | SDKROOT = iphoneos; 242 | TARGETED_DEVICE_FAMILY = 2; 243 | }; 244 | name = Release; 245 | }; 246 | 559E470E1370F6E400FEC4E5 /* Debug */ = { 247 | isa = XCBuildConfiguration; 248 | buildSettings = { 249 | ALWAYS_SEARCH_USER_PATHS = NO; 250 | COPY_PHASE_STRIP = NO; 251 | GCC_DYNAMIC_NO_PIC = NO; 252 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 253 | GCC_PREFIX_HEADER = "DynamicStorage/DynamicStorage-Prefix.pch"; 254 | INFOPLIST_FILE = "DynamicStorage/DynamicStorage-Info.plist"; 255 | PRODUCT_NAME = "$(TARGET_NAME)"; 256 | TARGETED_DEVICE_FAMILY = "1,2"; 257 | WRAPPER_EXTENSION = app; 258 | }; 259 | name = Debug; 260 | }; 261 | 559E470F1370F6E400FEC4E5 /* Release */ = { 262 | isa = XCBuildConfiguration; 263 | buildSettings = { 264 | ALWAYS_SEARCH_USER_PATHS = NO; 265 | COPY_PHASE_STRIP = YES; 266 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 267 | GCC_PREFIX_HEADER = "DynamicStorage/DynamicStorage-Prefix.pch"; 268 | INFOPLIST_FILE = "DynamicStorage/DynamicStorage-Info.plist"; 269 | PRODUCT_NAME = "$(TARGET_NAME)"; 270 | TARGETED_DEVICE_FAMILY = "1,2"; 271 | VALIDATE_PRODUCT = YES; 272 | WRAPPER_EXTENSION = app; 273 | }; 274 | name = Release; 275 | }; 276 | /* End XCBuildConfiguration section */ 277 | 278 | /* Begin XCConfigurationList section */ 279 | 559E46E61370F6E400FEC4E5 /* Build configuration list for PBXProject "DynamicStorage" */ = { 280 | isa = XCConfigurationList; 281 | buildConfigurations = ( 282 | 559E470B1370F6E400FEC4E5 /* Debug */, 283 | 559E470C1370F6E400FEC4E5 /* Release */, 284 | ); 285 | defaultConfigurationIsVisible = 0; 286 | defaultConfigurationName = Release; 287 | }; 288 | 559E470D1370F6E400FEC4E5 /* Build configuration list for PBXNativeTarget "DynamicStorage" */ = { 289 | isa = XCConfigurationList; 290 | buildConfigurations = ( 291 | 559E470E1370F6E400FEC4E5 /* Debug */, 292 | 559E470F1370F6E400FEC4E5 /* Release */, 293 | ); 294 | defaultConfigurationIsVisible = 0; 295 | }; 296 | /* End XCConfigurationList section */ 297 | }; 298 | rootObject = 559E46E31370F6E400FEC4E5 /* Project object */; 299 | } 300 | -------------------------------------------------------------------------------- /DynamicStorage/DynamicStorage.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /DynamicStorage/DynamicStorage/DDDynamicStorageObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // DDDynamicStorageObject.h 3 | // EmptyiPhone 4 | // 5 | // Created by Dave DeLong on 5/3/11. 6 | // Copyright 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface DDDynamicStorageObject : NSObject { 13 | @private 14 | NSMutableDictionary *_storage; 15 | } 16 | 17 | - (void)_printStorage; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /DynamicStorage/DynamicStorage/DDDynamicStorageObject.m: -------------------------------------------------------------------------------- 1 | // 2 | // DDDynamicStorageObject.m 3 | // EmptyiPhone 4 | // 5 | // Created by Dave DeLong on 5/3/11. 6 | // Copyright 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "DDDynamicStorageObject.h" 10 | #import 11 | 12 | static char valueKey = 1; 13 | 14 | @implementation DDDynamicStorageObject 15 | 16 | - (id)init { 17 | self = [super init]; 18 | if (self) { 19 | _storage = [[NSMutableDictionary alloc] init]; 20 | } 21 | return self; 22 | } 23 | - (void)dealloc { 24 | [_storage release]; 25 | [super dealloc]; 26 | } 27 | - (NSMutableDictionary *)storage { 28 | return _storage; 29 | } 30 | - (void)_printStorage { 31 | NSMutableDictionary *tmpStorage = [NSMutableDictionary dictionaryWithCapacity:[_storage count]]; 32 | for (NSString *propertyName in _storage) { 33 | NSObject *objectHolder = [_storage objectForKey:propertyName]; 34 | id propertyValue = objc_getAssociatedObject(objectHolder, &valueKey); 35 | if (propertyValue == nil) { 36 | propertyValue = [NSNull null]; 37 | } 38 | [tmpStorage setObject:propertyValue forKey:propertyName]; 39 | } 40 | NSLog(@"%@", tmpStorage); 41 | } 42 | 43 | + (BOOL)resolveInstanceMethod:(SEL)sel { 44 | const char *rawName = sel_getName(sel); 45 | NSString *name = NSStringFromSelector(sel); 46 | 47 | NSString *propertyName = nil; 48 | 49 | if ([name hasPrefix:@"set"]) { 50 | propertyName = [NSString stringWithFormat:@"%c%s", tolower(rawName[3]), (rawName+4)]; 51 | } else if ([name hasPrefix:@"is"]) { 52 | propertyName = [NSString stringWithFormat:@"%c%s", tolower(rawName[2]), (rawName+3)]; 53 | } else { 54 | propertyName = name; 55 | } 56 | propertyName = [propertyName stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@":"]]; 57 | 58 | Class cls = self; 59 | objc_property_t property = class_getProperty(self, [propertyName UTF8String]); 60 | if (property == NULL) { 61 | //unable to find property 62 | //let's see if we can brute-force find it 63 | while (cls != nil) { 64 | unsigned int count = 0; 65 | objc_property_t *allProperties = class_copyPropertyList(cls, &count); 66 | for (int i = 0; i < count; ++i) { 67 | objc_property_t aProperty = allProperties[i]; 68 | NSString *propertyInfo = [NSString stringWithUTF8String:property_getAttributes(aProperty)]; 69 | if ([propertyInfo rangeOfString:name].location != NSNotFound) { 70 | property = aProperty; 71 | break; 72 | } 73 | } 74 | if (allProperties) { 75 | free(allProperties); 76 | } 77 | if (property != NULL) { break; } 78 | } 79 | } 80 | 81 | if (property == NULL) { 82 | IMP imp = class_getMethodImplementation(self, sel); 83 | return (imp != NULL); 84 | } 85 | 86 | const char *rawPropertyName = property_getName(property); 87 | propertyName = [NSString stringWithUTF8String:rawPropertyName]; 88 | 89 | NSString *getterName = nil; 90 | NSString *setterName = nil; 91 | NSString *propertyType = nil; 92 | BOOL isReadonly = NO; 93 | BOOL isAtomic = YES; 94 | objc_AssociationPolicy policy = OBJC_ASSOCIATION_ASSIGN; 95 | 96 | NSString *propertyInfo = [NSString stringWithUTF8String:property_getAttributes(property)]; 97 | NSArray *propertyAttributes = [propertyInfo componentsSeparatedByString:@","]; 98 | for (NSString *attribute in propertyAttributes) { 99 | if ([attribute hasPrefix:@"G"] && getterName == nil) { 100 | getterName = [attribute substringFromIndex:1]; 101 | } else if ([attribute hasPrefix:@"S"] && setterName == nil) { 102 | setterName = [attribute substringFromIndex:1]; 103 | } else if ([attribute hasPrefix:@"t"] && propertyType == nil) { 104 | propertyType = [attribute substringFromIndex:1]; 105 | } else if ([attribute isEqualToString:@"N"]) { 106 | isAtomic = NO; 107 | } else if ([attribute isEqualToString:@"R"]) { 108 | isReadonly = YES; 109 | } else if ([attribute isEqualToString:@"C"]) { 110 | policy = OBJC_ASSOCIATION_COPY; 111 | } else if ([attribute isEqualToString:@"&"]) { 112 | policy = OBJC_ASSOCIATION_RETAIN; 113 | } 114 | } 115 | 116 | if (isAtomic) { 117 | NSLog(@"unable to generate truly atomic accessors for \"%@.%@\". Sorry!", NSStringFromClass(cls), propertyName); 118 | } else { 119 | if (policy == OBJC_ASSOCIATION_COPY) { 120 | policy = OBJC_ASSOCIATION_COPY_NONATOMIC; 121 | } else if (policy == OBJC_ASSOCIATION_RETAIN) { 122 | policy = OBJC_ASSOCIATION_RETAIN_NONATOMIC; 123 | } 124 | } 125 | 126 | if (getterName == nil) { 127 | getterName = propertyName; 128 | } 129 | if (setterName == nil) { 130 | setterName = [NSString stringWithFormat:@"set%c%s:", toupper(rawPropertyName[0]), (rawPropertyName+1)]; 131 | } 132 | 133 | id(^getterBlock)(id) = ^id(id _s) { 134 | NSObject *v = [[_s storage] objectForKey:propertyName]; 135 | return objc_getAssociatedObject(v, &valueKey); 136 | }; 137 | void(^setterBlock)(id,id) = ^(id _s, id _v) { 138 | NSObject *o = [[NSObject alloc] init]; 139 | objc_setAssociatedObject(o, &valueKey, _v, policy); 140 | [[_s storage] setObject:o forKey:propertyName]; 141 | [o release]; 142 | }; 143 | 144 | IMP getterIMP = imp_implementationWithBlock((void*)getterBlock); 145 | IMP setterIMP = imp_implementationWithBlock((void*)setterBlock); 146 | 147 | BOOL getterAdded = NO; 148 | BOOL setterAdded = NO; 149 | 150 | if (getterIMP != NULL) { 151 | getterAdded = class_addMethod(cls, NSSelectorFromString(getterName), getterIMP, "@@:"); 152 | } 153 | 154 | if (isReadonly == NO) { 155 | if (setterIMP != NULL) { 156 | setterAdded = class_addMethod(cls, NSSelectorFromString(setterName), setterIMP, "v@:@"); 157 | } 158 | } else { 159 | imp_removeBlock(setterIMP); 160 | setterAdded = YES; 161 | } 162 | 163 | if (!getterAdded || !setterAdded) { 164 | NSLog(@"===================="); 165 | NSLog(@"error adding methods"); 166 | NSLog(@"class: %@", NSStringFromClass(cls)); 167 | NSLog(@"setter: %@ => added?:%d", setterName, setterAdded); 168 | NSLog(@"getter: %@ => added?:%d", getterName, getterAdded); 169 | } 170 | 171 | return YES; 172 | } 173 | 174 | @end 175 | -------------------------------------------------------------------------------- /DynamicStorage/DynamicStorage/DynamicStorage-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIconFile 12 | 13 | CFBundleIdentifier 14 | com.davedelong.${PRODUCT_NAME:rfc1034identifier} 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | ${PRODUCT_NAME} 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | 1.0 23 | CFBundleSignature 24 | ???? 25 | CFBundleVersion 26 | 1.0 27 | LSRequiresIPhoneOS 28 | 29 | NSMainNibFile 30 | MainWindow 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationPortraitUpsideDown 35 | UIInterfaceOrientationLandscapeLeft 36 | UIInterfaceOrientationLandscapeRight 37 | 38 | UISupportedInterfaceOrientations~ipad 39 | 40 | UIInterfaceOrientationPortrait 41 | UIInterfaceOrientationPortraitUpsideDown 42 | UIInterfaceOrientationLandscapeLeft 43 | UIInterfaceOrientationLandscapeRight 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /DynamicStorage/DynamicStorage/DynamicStorage-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'DynamicStorage' target in the 'DynamicStorage' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_3_0 8 | #warning "This project uses features only available in iPhone SDK 3.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /DynamicStorage/DynamicStorage/DynamicStorageAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // DynamicStorageAppDelegate.h 3 | // DynamicStorage 4 | // 5 | // Created by Dave DeLong on 5/3/11. 6 | // Copyright 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class DynamicStorageViewController; 12 | 13 | @interface DynamicStorageAppDelegate : NSObject { 14 | 15 | } 16 | 17 | @property (nonatomic, retain) IBOutlet UIWindow *window; 18 | 19 | @property (nonatomic, retain) IBOutlet DynamicStorageViewController *viewController; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /DynamicStorage/DynamicStorage/DynamicStorageAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // DynamicStorageAppDelegate.m 3 | // DynamicStorage 4 | // 5 | // Created by Dave DeLong on 5/3/11. 6 | // Copyright 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "DynamicStorageAppDelegate.h" 10 | 11 | #import "DynamicStorageViewController.h" 12 | 13 | @implementation DynamicStorageAppDelegate 14 | 15 | 16 | @synthesize window=_window; 17 | 18 | @synthesize viewController=_viewController; 19 | 20 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 21 | { 22 | // Override point for customization after application launch. 23 | 24 | self.window.rootViewController = self.viewController; 25 | [self.window makeKeyAndVisible]; 26 | return YES; 27 | } 28 | 29 | - (void)applicationWillResignActive:(UIApplication *)application 30 | { 31 | /* 32 | Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 33 | Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 34 | */ 35 | } 36 | 37 | - (void)applicationDidEnterBackground:(UIApplication *)application 38 | { 39 | /* 40 | Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 41 | If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 42 | */ 43 | } 44 | 45 | - (void)applicationWillEnterForeground:(UIApplication *)application 46 | { 47 | /* 48 | Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 49 | */ 50 | } 51 | 52 | - (void)applicationDidBecomeActive:(UIApplication *)application 53 | { 54 | /* 55 | Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 56 | */ 57 | } 58 | 59 | - (void)applicationWillTerminate:(UIApplication *)application 60 | { 61 | /* 62 | Called when the application is about to terminate. 63 | Save data if appropriate. 64 | See also applicationDidEnterBackground:. 65 | */ 66 | } 67 | 68 | - (void)dealloc 69 | { 70 | [_window release]; 71 | [_viewController release]; 72 | [super dealloc]; 73 | } 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /DynamicStorage/DynamicStorage/DynamicStorageViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DynamicStorageViewController.h 3 | // DynamicStorage 4 | // 5 | // Created by Dave DeLong on 5/3/11. 6 | // Copyright 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DynamicStorageViewController : UIViewController { 12 | 13 | } 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /DynamicStorage/DynamicStorage/DynamicStorageViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DynamicStorageViewController.m 3 | // DynamicStorage 4 | // 5 | // Created by Dave DeLong on 5/3/11. 6 | // Copyright 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "DynamicStorageViewController.h" 10 | #import "SimpleStorage.h" 11 | 12 | @implementation DynamicStorageViewController 13 | 14 | - (void)dealloc 15 | { 16 | [super dealloc]; 17 | } 18 | 19 | - (void)didReceiveMemoryWarning 20 | { 21 | // Releases the view if it doesn't have a superview. 22 | [super didReceiveMemoryWarning]; 23 | 24 | // Release any cached data, images, etc that aren't in use. 25 | } 26 | 27 | #pragma mark - View lifecycle 28 | 29 | // Implement viewDidLoad to do additional setup after loading the view, typically from a nib. 30 | - (void)viewDidLoad 31 | { 32 | SimpleStorage *simple = [[SimpleStorage alloc] init]; 33 | [simple setCustomly:[NSDate date]]; 34 | [simple setDelegate:self]; 35 | [simple setCopiedArray:[NSArray arrayWithObject:@"foo!"]]; 36 | [simple setStringValue:@"this is a string"]; 37 | NSLog(@"%@", [simple numberValue]); //should log NULL 38 | 39 | [simple _printStorage]; 40 | 41 | [super viewDidLoad]; 42 | } 43 | 44 | - (void)viewDidUnload 45 | { 46 | [super viewDidUnload]; 47 | // Release any retained subviews of the main view. 48 | // e.g. self.myOutlet = nil; 49 | } 50 | 51 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 52 | { 53 | // Return YES for supported orientations 54 | return YES; 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /DynamicStorage/DynamicStorage/SimpleStorage.h: -------------------------------------------------------------------------------- 1 | // 2 | // SimpleStorage.h 3 | // DynamicStorage 4 | // 5 | // Created by Dave DeLong on 5/3/11. 6 | // Copyright 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "DDDynamicStorageObject.h" 11 | 12 | @interface SimpleStorage : DDDynamicStorageObject { 13 | 14 | } 15 | 16 | @property (nonatomic, retain) NSString *stringValue; 17 | @property (nonatomic, readonly) NSNumber *numberValue; 18 | @property (assign) id delegate; 19 | @property (setter=setCustomly:,getter=customly, retain) NSDate *date; 20 | @property (copy) NSArray *copiedArray; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /DynamicStorage/DynamicStorage/SimpleStorage.m: -------------------------------------------------------------------------------- 1 | // 2 | // SimpleStorage.m 3 | // DynamicStorage 4 | // 5 | // Created by Dave DeLong on 5/3/11. 6 | // Copyright 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "SimpleStorage.h" 10 | 11 | 12 | @implementation SimpleStorage 13 | 14 | @dynamic stringValue; 15 | @dynamic numberValue; 16 | @dynamic delegate; 17 | @dynamic date; 18 | @dynamic copiedArray; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /DynamicStorage/DynamicStorage/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /DynamicStorage/DynamicStorage/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // DynamicStorage 4 | // 5 | // Created by Dave DeLong on 5/3/11. 6 | // Copyright 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 14 | int retVal = UIApplicationMain(argc, argv, nil, nil); 15 | [pool release]; 16 | return retVal; 17 | } 18 | -------------------------------------------------------------------------------- /FaultingArray/FaultingArray.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 55951DBC14C9291B00E4A63E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 55951DBB14C9291B00E4A63E /* Foundation.framework */; }; 11 | 55951DBF14C9291B00E4A63E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 55951DBE14C9291B00E4A63E /* main.m */; }; 12 | 55951DC314C9291B00E4A63E /* FaultingArray.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 55951DC214C9291B00E4A63E /* FaultingArray.1 */; }; 13 | 55951DCB14C9292F00E4A63E /* DDFaultingArray.m in Sources */ = {isa = PBXBuildFile; fileRef = 55951DCA14C9292F00E4A63E /* DDFaultingArray.m */; }; 14 | /* End PBXBuildFile section */ 15 | 16 | /* Begin PBXCopyFilesBuildPhase section */ 17 | 55951DB514C9291B00E4A63E /* CopyFiles */ = { 18 | isa = PBXCopyFilesBuildPhase; 19 | buildActionMask = 2147483647; 20 | dstPath = /usr/share/man/man1/; 21 | dstSubfolderSpec = 0; 22 | files = ( 23 | 55951DC314C9291B00E4A63E /* FaultingArray.1 in CopyFiles */, 24 | ); 25 | runOnlyForDeploymentPostprocessing = 1; 26 | }; 27 | /* End PBXCopyFilesBuildPhase section */ 28 | 29 | /* Begin PBXFileReference section */ 30 | 55951DB714C9291B00E4A63E /* FaultingArray */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = FaultingArray; sourceTree = BUILT_PRODUCTS_DIR; }; 31 | 55951DBB14C9291B00E4A63E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 32 | 55951DBE14C9291B00E4A63E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 33 | 55951DC114C9291B00E4A63E /* FaultingArray-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FaultingArray-Prefix.pch"; sourceTree = ""; }; 34 | 55951DC214C9291B00E4A63E /* FaultingArray.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = FaultingArray.1; sourceTree = ""; }; 35 | 55951DC914C9292F00E4A63E /* DDFaultingArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDFaultingArray.h; sourceTree = ""; }; 36 | 55951DCA14C9292F00E4A63E /* DDFaultingArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDFaultingArray.m; sourceTree = ""; }; 37 | /* End PBXFileReference section */ 38 | 39 | /* Begin PBXFrameworksBuildPhase section */ 40 | 55951DB414C9291B00E4A63E /* Frameworks */ = { 41 | isa = PBXFrameworksBuildPhase; 42 | buildActionMask = 2147483647; 43 | files = ( 44 | 55951DBC14C9291B00E4A63E /* Foundation.framework in Frameworks */, 45 | ); 46 | runOnlyForDeploymentPostprocessing = 0; 47 | }; 48 | /* End PBXFrameworksBuildPhase section */ 49 | 50 | /* Begin PBXGroup section */ 51 | 55951DAC14C9291B00E4A63E = { 52 | isa = PBXGroup; 53 | children = ( 54 | 55951DBD14C9291B00E4A63E /* FaultingArray */, 55 | 55951DBA14C9291B00E4A63E /* Frameworks */, 56 | 55951DB814C9291B00E4A63E /* Products */, 57 | ); 58 | sourceTree = ""; 59 | }; 60 | 55951DB814C9291B00E4A63E /* Products */ = { 61 | isa = PBXGroup; 62 | children = ( 63 | 55951DB714C9291B00E4A63E /* FaultingArray */, 64 | ); 65 | name = Products; 66 | sourceTree = ""; 67 | }; 68 | 55951DBA14C9291B00E4A63E /* Frameworks */ = { 69 | isa = PBXGroup; 70 | children = ( 71 | 55951DBB14C9291B00E4A63E /* Foundation.framework */, 72 | ); 73 | name = Frameworks; 74 | sourceTree = ""; 75 | }; 76 | 55951DBD14C9291B00E4A63E /* FaultingArray */ = { 77 | isa = PBXGroup; 78 | children = ( 79 | 55951DBE14C9291B00E4A63E /* main.m */, 80 | 55951DC914C9292F00E4A63E /* DDFaultingArray.h */, 81 | 55951DCA14C9292F00E4A63E /* DDFaultingArray.m */, 82 | 55951DC214C9291B00E4A63E /* FaultingArray.1 */, 83 | 55951DC014C9291B00E4A63E /* Supporting Files */, 84 | ); 85 | path = FaultingArray; 86 | sourceTree = ""; 87 | }; 88 | 55951DC014C9291B00E4A63E /* Supporting Files */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | 55951DC114C9291B00E4A63E /* FaultingArray-Prefix.pch */, 92 | ); 93 | name = "Supporting Files"; 94 | sourceTree = ""; 95 | }; 96 | /* End PBXGroup section */ 97 | 98 | /* Begin PBXNativeTarget section */ 99 | 55951DB614C9291B00E4A63E /* FaultingArray */ = { 100 | isa = PBXNativeTarget; 101 | buildConfigurationList = 55951DC614C9291B00E4A63E /* Build configuration list for PBXNativeTarget "FaultingArray" */; 102 | buildPhases = ( 103 | 55951DB314C9291B00E4A63E /* Sources */, 104 | 55951DB414C9291B00E4A63E /* Frameworks */, 105 | 55951DB514C9291B00E4A63E /* CopyFiles */, 106 | ); 107 | buildRules = ( 108 | ); 109 | dependencies = ( 110 | ); 111 | name = FaultingArray; 112 | productName = FaultingArray; 113 | productReference = 55951DB714C9291B00E4A63E /* FaultingArray */; 114 | productType = "com.apple.product-type.tool"; 115 | }; 116 | /* End PBXNativeTarget section */ 117 | 118 | /* Begin PBXProject section */ 119 | 55951DAE14C9291B00E4A63E /* Project object */ = { 120 | isa = PBXProject; 121 | attributes = { 122 | LastUpgradeCheck = 0420; 123 | }; 124 | buildConfigurationList = 55951DB114C9291B00E4A63E /* Build configuration list for PBXProject "FaultingArray" */; 125 | compatibilityVersion = "Xcode 3.2"; 126 | developmentRegion = English; 127 | hasScannedForEncodings = 0; 128 | knownRegions = ( 129 | en, 130 | ); 131 | mainGroup = 55951DAC14C9291B00E4A63E; 132 | productRefGroup = 55951DB814C9291B00E4A63E /* Products */; 133 | projectDirPath = ""; 134 | projectRoot = ""; 135 | targets = ( 136 | 55951DB614C9291B00E4A63E /* FaultingArray */, 137 | ); 138 | }; 139 | /* End PBXProject section */ 140 | 141 | /* Begin PBXSourcesBuildPhase section */ 142 | 55951DB314C9291B00E4A63E /* Sources */ = { 143 | isa = PBXSourcesBuildPhase; 144 | buildActionMask = 2147483647; 145 | files = ( 146 | 55951DBF14C9291B00E4A63E /* main.m in Sources */, 147 | 55951DCB14C9292F00E4A63E /* DDFaultingArray.m in Sources */, 148 | ); 149 | runOnlyForDeploymentPostprocessing = 0; 150 | }; 151 | /* End PBXSourcesBuildPhase section */ 152 | 153 | /* Begin XCBuildConfiguration section */ 154 | 55951DC414C9291B00E4A63E /* Debug */ = { 155 | isa = XCBuildConfiguration; 156 | buildSettings = { 157 | ALWAYS_SEARCH_USER_PATHS = NO; 158 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 159 | COPY_PHASE_STRIP = NO; 160 | GCC_C_LANGUAGE_STANDARD = gnu99; 161 | GCC_DYNAMIC_NO_PIC = NO; 162 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 163 | GCC_OPTIMIZATION_LEVEL = 0; 164 | GCC_PREPROCESSOR_DEFINITIONS = ( 165 | "DEBUG=1", 166 | "$(inherited)", 167 | ); 168 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 169 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 170 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 171 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 172 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 173 | GCC_WARN_UNUSED_VARIABLE = YES; 174 | MACOSX_DEPLOYMENT_TARGET = 10.7; 175 | ONLY_ACTIVE_ARCH = YES; 176 | SDKROOT = macosx; 177 | }; 178 | name = Debug; 179 | }; 180 | 55951DC514C9291B00E4A63E /* Release */ = { 181 | isa = XCBuildConfiguration; 182 | buildSettings = { 183 | ALWAYS_SEARCH_USER_PATHS = NO; 184 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 185 | COPY_PHASE_STRIP = YES; 186 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 187 | GCC_C_LANGUAGE_STANDARD = gnu99; 188 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 189 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 190 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 191 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 192 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 193 | GCC_WARN_UNUSED_VARIABLE = YES; 194 | MACOSX_DEPLOYMENT_TARGET = 10.7; 195 | SDKROOT = macosx; 196 | }; 197 | name = Release; 198 | }; 199 | 55951DC714C9291B00E4A63E /* Debug */ = { 200 | isa = XCBuildConfiguration; 201 | buildSettings = { 202 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 203 | GCC_PREFIX_HEADER = "FaultingArray/FaultingArray-Prefix.pch"; 204 | PRODUCT_NAME = "$(TARGET_NAME)"; 205 | }; 206 | name = Debug; 207 | }; 208 | 55951DC814C9291B00E4A63E /* Release */ = { 209 | isa = XCBuildConfiguration; 210 | buildSettings = { 211 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 212 | GCC_PREFIX_HEADER = "FaultingArray/FaultingArray-Prefix.pch"; 213 | PRODUCT_NAME = "$(TARGET_NAME)"; 214 | }; 215 | name = Release; 216 | }; 217 | /* End XCBuildConfiguration section */ 218 | 219 | /* Begin XCConfigurationList section */ 220 | 55951DB114C9291B00E4A63E /* Build configuration list for PBXProject "FaultingArray" */ = { 221 | isa = XCConfigurationList; 222 | buildConfigurations = ( 223 | 55951DC414C9291B00E4A63E /* Debug */, 224 | 55951DC514C9291B00E4A63E /* Release */, 225 | ); 226 | defaultConfigurationIsVisible = 0; 227 | defaultConfigurationName = Release; 228 | }; 229 | 55951DC614C9291B00E4A63E /* Build configuration list for PBXNativeTarget "FaultingArray" */ = { 230 | isa = XCConfigurationList; 231 | buildConfigurations = ( 232 | 55951DC714C9291B00E4A63E /* Debug */, 233 | 55951DC814C9291B00E4A63E /* Release */, 234 | ); 235 | defaultConfigurationIsVisible = 0; 236 | }; 237 | /* End XCConfigurationList section */ 238 | }; 239 | rootObject = 55951DAE14C9291B00E4A63E /* Project object */; 240 | } 241 | -------------------------------------------------------------------------------- /FaultingArray/FaultingArray.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /FaultingArray/FaultingArray/DDFaultingArray.h: -------------------------------------------------------------------------------- 1 | // 2 | // DDFaultingArray.h 3 | // FaultingArray 4 | // 5 | // Created by Dave DeLong on 1/19/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef id(^DDFaultingArrayFaulter)(NSUInteger idx); 12 | 13 | @interface DDFaultingArray : NSArray 14 | 15 | @property (nonatomic, copy) DDFaultingArrayFaulter faulter; 16 | 17 | - (id)initWithCapacity:(NSUInteger)capacity; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /FaultingArray/FaultingArray/DDFaultingArray.m: -------------------------------------------------------------------------------- 1 | // 2 | // DDFaultingArray.m 3 | // FaultingArray 4 | // 5 | // Created by Dave DeLong on 1/19/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "DDFaultingArray.h" 10 | 11 | @implementation DDFaultingArray { 12 | NSMutableArray *_storage; 13 | } 14 | 15 | @synthesize faulter=_faulter; 16 | 17 | - (id)initWithCapacity:(NSUInteger)capacity { 18 | self = [super init]; 19 | if (self) { 20 | _storage = [[NSMutableArray alloc] initWithCapacity:capacity]; 21 | for (NSUInteger i = 0; i < capacity; ++i) { 22 | [_storage addObject:[NSNull null]]; 23 | } 24 | } 25 | return self; 26 | } 27 | 28 | - (void)dealloc { 29 | [_faulter release]; 30 | [super dealloc]; 31 | } 32 | 33 | - (NSUInteger)count { 34 | return [_storage count]; 35 | } 36 | 37 | - (id)objectAtIndex:(NSUInteger)index { 38 | id obj = [_storage objectAtIndex:index]; 39 | if (obj == [NSNull null]) { 40 | // ask someone for our object 41 | 42 | if (!_faulter) { 43 | [NSException raise:NSInternalInconsistencyException format:@"Can't fault without a faulter! This is your fault!"]; 44 | } 45 | 46 | obj = _faulter(index); 47 | 48 | if (obj == nil) { 49 | [NSException raise:NSInternalInconsistencyException format:@"May not return nil for a faulted object"]; 50 | } 51 | 52 | [_storage replaceObjectAtIndex:index withObject:obj]; 53 | } 54 | return obj; 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /FaultingArray/FaultingArray/FaultingArray-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'FaultingArray' target in the 'FaultingArray' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /FaultingArray/FaultingArray/FaultingArray.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 1/19/12 \" DATE 7 | .Dt FaultingArray 1 \" Program name and manual section number 8 | .Os Darwin 9 | .Sh NAME \" Section Header - required - don't modify 10 | .Nm FaultingArray, 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 -------------------------------------------------------------------------------- /FaultingArray/FaultingArray/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // FaultingArray 4 | // 5 | // Created by Dave DeLong on 1/19/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "DDFaultingArray.h" 11 | 12 | int main (int argc, const char * argv[]) 13 | { 14 | 15 | @autoreleasepool { 16 | 17 | 18 | DDFaultingArray *array = [[DDFaultingArray alloc] initWithCapacity:100]; 19 | [array setFaulter:^(NSUInteger idx) { 20 | NSLog(@"requesting object at index: %lu", idx); 21 | return [NSNumber numberWithUnsignedInteger:(idx*idx)]; 22 | }]; 23 | 24 | NSLog(@"%@", array); 25 | 26 | } 27 | return 0; 28 | } 29 | 30 | -------------------------------------------------------------------------------- /GrandSuper/GrandSuper.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 559CB8F6148ADA0E00005B5A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 559CB8F5148ADA0E00005B5A /* Foundation.framework */; }; 11 | 559CB8F9148ADA0E00005B5A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 559CB8F8148ADA0E00005B5A /* main.m */; }; 12 | 559CB8FD148ADA0E00005B5A /* GrandSuper.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 559CB8FC148ADA0E00005B5A /* GrandSuper.1 */; }; 13 | 559CB905148ADA3200005B5A /* DDSuperProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 559CB904148ADA3200005B5A /* DDSuperProxy.m */; }; 14 | /* End PBXBuildFile section */ 15 | 16 | /* Begin PBXCopyFilesBuildPhase section */ 17 | 559CB8EF148ADA0E00005B5A /* CopyFiles */ = { 18 | isa = PBXCopyFilesBuildPhase; 19 | buildActionMask = 2147483647; 20 | dstPath = /usr/share/man/man1/; 21 | dstSubfolderSpec = 0; 22 | files = ( 23 | 559CB8FD148ADA0E00005B5A /* GrandSuper.1 in CopyFiles */, 24 | ); 25 | runOnlyForDeploymentPostprocessing = 1; 26 | }; 27 | /* End PBXCopyFilesBuildPhase section */ 28 | 29 | /* Begin PBXFileReference section */ 30 | 559CB8F1148ADA0E00005B5A /* GrandSuper */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = GrandSuper; sourceTree = BUILT_PRODUCTS_DIR; }; 31 | 559CB8F5148ADA0E00005B5A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 32 | 559CB8F8148ADA0E00005B5A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 33 | 559CB8FB148ADA0E00005B5A /* GrandSuper-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "GrandSuper-Prefix.pch"; sourceTree = ""; }; 34 | 559CB8FC148ADA0E00005B5A /* GrandSuper.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = GrandSuper.1; sourceTree = ""; }; 35 | 559CB903148ADA3200005B5A /* DDSuperProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDSuperProxy.h; sourceTree = ""; }; 36 | 559CB904148ADA3200005B5A /* DDSuperProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DDSuperProxy.m; sourceTree = ""; }; 37 | /* End PBXFileReference section */ 38 | 39 | /* Begin PBXFrameworksBuildPhase section */ 40 | 559CB8EE148ADA0E00005B5A /* Frameworks */ = { 41 | isa = PBXFrameworksBuildPhase; 42 | buildActionMask = 2147483647; 43 | files = ( 44 | 559CB8F6148ADA0E00005B5A /* Foundation.framework in Frameworks */, 45 | ); 46 | runOnlyForDeploymentPostprocessing = 0; 47 | }; 48 | /* End PBXFrameworksBuildPhase section */ 49 | 50 | /* Begin PBXGroup section */ 51 | 559CB8E6148ADA0E00005B5A = { 52 | isa = PBXGroup; 53 | children = ( 54 | 559CB8F7148ADA0E00005B5A /* GrandSuper */, 55 | 559CB8F4148ADA0E00005B5A /* Frameworks */, 56 | 559CB8F2148ADA0E00005B5A /* Products */, 57 | ); 58 | sourceTree = ""; 59 | }; 60 | 559CB8F2148ADA0E00005B5A /* Products */ = { 61 | isa = PBXGroup; 62 | children = ( 63 | 559CB8F1148ADA0E00005B5A /* GrandSuper */, 64 | ); 65 | name = Products; 66 | sourceTree = ""; 67 | }; 68 | 559CB8F4148ADA0E00005B5A /* Frameworks */ = { 69 | isa = PBXGroup; 70 | children = ( 71 | 559CB8F5148ADA0E00005B5A /* Foundation.framework */, 72 | ); 73 | name = Frameworks; 74 | sourceTree = ""; 75 | }; 76 | 559CB8F7148ADA0E00005B5A /* GrandSuper */ = { 77 | isa = PBXGroup; 78 | children = ( 79 | 559CB8F8148ADA0E00005B5A /* main.m */, 80 | 559CB903148ADA3200005B5A /* DDSuperProxy.h */, 81 | 559CB904148ADA3200005B5A /* DDSuperProxy.m */, 82 | 559CB8FC148ADA0E00005B5A /* GrandSuper.1 */, 83 | 559CB8FA148ADA0E00005B5A /* Supporting Files */, 84 | ); 85 | path = GrandSuper; 86 | sourceTree = ""; 87 | }; 88 | 559CB8FA148ADA0E00005B5A /* Supporting Files */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | 559CB8FB148ADA0E00005B5A /* GrandSuper-Prefix.pch */, 92 | ); 93 | name = "Supporting Files"; 94 | sourceTree = ""; 95 | }; 96 | /* End PBXGroup section */ 97 | 98 | /* Begin PBXNativeTarget section */ 99 | 559CB8F0148ADA0E00005B5A /* GrandSuper */ = { 100 | isa = PBXNativeTarget; 101 | buildConfigurationList = 559CB900148ADA0E00005B5A /* Build configuration list for PBXNativeTarget "GrandSuper" */; 102 | buildPhases = ( 103 | 559CB8ED148ADA0E00005B5A /* Sources */, 104 | 559CB8EE148ADA0E00005B5A /* Frameworks */, 105 | 559CB8EF148ADA0E00005B5A /* CopyFiles */, 106 | ); 107 | buildRules = ( 108 | ); 109 | dependencies = ( 110 | ); 111 | name = GrandSuper; 112 | productName = GrandSuper; 113 | productReference = 559CB8F1148ADA0E00005B5A /* GrandSuper */; 114 | productType = "com.apple.product-type.tool"; 115 | }; 116 | /* End PBXNativeTarget section */ 117 | 118 | /* Begin PBXProject section */ 119 | 559CB8E8148ADA0E00005B5A /* Project object */ = { 120 | isa = PBXProject; 121 | attributes = { 122 | LastUpgradeCheck = 0420; 123 | }; 124 | buildConfigurationList = 559CB8EB148ADA0E00005B5A /* Build configuration list for PBXProject "GrandSuper" */; 125 | compatibilityVersion = "Xcode 3.2"; 126 | developmentRegion = English; 127 | hasScannedForEncodings = 0; 128 | knownRegions = ( 129 | en, 130 | ); 131 | mainGroup = 559CB8E6148ADA0E00005B5A; 132 | productRefGroup = 559CB8F2148ADA0E00005B5A /* Products */; 133 | projectDirPath = ""; 134 | projectRoot = ""; 135 | targets = ( 136 | 559CB8F0148ADA0E00005B5A /* GrandSuper */, 137 | ); 138 | }; 139 | /* End PBXProject section */ 140 | 141 | /* Begin PBXSourcesBuildPhase section */ 142 | 559CB8ED148ADA0E00005B5A /* Sources */ = { 143 | isa = PBXSourcesBuildPhase; 144 | buildActionMask = 2147483647; 145 | files = ( 146 | 559CB8F9148ADA0E00005B5A /* main.m in Sources */, 147 | 559CB905148ADA3200005B5A /* DDSuperProxy.m in Sources */, 148 | ); 149 | runOnlyForDeploymentPostprocessing = 0; 150 | }; 151 | /* End PBXSourcesBuildPhase section */ 152 | 153 | /* Begin XCBuildConfiguration section */ 154 | 559CB8FE148ADA0E00005B5A /* Debug */ = { 155 | isa = XCBuildConfiguration; 156 | buildSettings = { 157 | ALWAYS_SEARCH_USER_PATHS = NO; 158 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 159 | COPY_PHASE_STRIP = NO; 160 | GCC_C_LANGUAGE_STANDARD = gnu99; 161 | GCC_DYNAMIC_NO_PIC = NO; 162 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 163 | GCC_OPTIMIZATION_LEVEL = 0; 164 | GCC_PREPROCESSOR_DEFINITIONS = ( 165 | "DEBUG=1", 166 | "$(inherited)", 167 | ); 168 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 169 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 170 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 171 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 172 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 173 | GCC_WARN_UNUSED_VARIABLE = YES; 174 | MACOSX_DEPLOYMENT_TARGET = 10.7; 175 | ONLY_ACTIVE_ARCH = YES; 176 | SDKROOT = macosx; 177 | }; 178 | name = Debug; 179 | }; 180 | 559CB8FF148ADA0E00005B5A /* Release */ = { 181 | isa = XCBuildConfiguration; 182 | buildSettings = { 183 | ALWAYS_SEARCH_USER_PATHS = NO; 184 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 185 | COPY_PHASE_STRIP = YES; 186 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 187 | GCC_C_LANGUAGE_STANDARD = gnu99; 188 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 189 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 190 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 191 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 192 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 193 | GCC_WARN_UNUSED_VARIABLE = YES; 194 | MACOSX_DEPLOYMENT_TARGET = 10.7; 195 | SDKROOT = macosx; 196 | }; 197 | name = Release; 198 | }; 199 | 559CB901148ADA0E00005B5A /* Debug */ = { 200 | isa = XCBuildConfiguration; 201 | buildSettings = { 202 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 203 | GCC_PREFIX_HEADER = "GrandSuper/GrandSuper-Prefix.pch"; 204 | PRODUCT_NAME = "$(TARGET_NAME)"; 205 | }; 206 | name = Debug; 207 | }; 208 | 559CB902148ADA0E00005B5A /* Release */ = { 209 | isa = XCBuildConfiguration; 210 | buildSettings = { 211 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 212 | GCC_PREFIX_HEADER = "GrandSuper/GrandSuper-Prefix.pch"; 213 | PRODUCT_NAME = "$(TARGET_NAME)"; 214 | }; 215 | name = Release; 216 | }; 217 | /* End XCBuildConfiguration section */ 218 | 219 | /* Begin XCConfigurationList section */ 220 | 559CB8EB148ADA0E00005B5A /* Build configuration list for PBXProject "GrandSuper" */ = { 221 | isa = XCConfigurationList; 222 | buildConfigurations = ( 223 | 559CB8FE148ADA0E00005B5A /* Debug */, 224 | 559CB8FF148ADA0E00005B5A /* Release */, 225 | ); 226 | defaultConfigurationIsVisible = 0; 227 | defaultConfigurationName = Release; 228 | }; 229 | 559CB900148ADA0E00005B5A /* Build configuration list for PBXNativeTarget "GrandSuper" */ = { 230 | isa = XCConfigurationList; 231 | buildConfigurations = ( 232 | 559CB901148ADA0E00005B5A /* Debug */, 233 | 559CB902148ADA0E00005B5A /* Release */, 234 | ); 235 | defaultConfigurationIsVisible = 0; 236 | }; 237 | /* End XCConfigurationList section */ 238 | }; 239 | rootObject = 559CB8E8148ADA0E00005B5A /* Project object */; 240 | } 241 | -------------------------------------------------------------------------------- /GrandSuper/GrandSuper.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /GrandSuper/GrandSuper/DDSuperProxy.h: -------------------------------------------------------------------------------- 1 | // 2 | // DDSuperProxy.h 3 | // GrandSuper 4 | // 5 | // Created by Dave DeLong on 12/3/11. 6 | // Copyright (c) 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DDSuperProxy : NSProxy { 12 | Class _context; 13 | int _level; 14 | id _target; 15 | } 16 | 17 | - (id)initWithProxy:(id)proxyTarget superLevel:(int)level originalContext:(const char *)oContext; 18 | 19 | @end 20 | 21 | static inline id __parent(id self, int level, const char *context) { 22 | if (level == 0) { return self; } 23 | return [[[DDSuperProxy alloc] initWithProxy:self superLevel:level originalContext:context] autorelease]; 24 | } 25 | 26 | #define parent(_l) __parent(self, (_l), __PRETTY_FUNCTION__) 27 | #define grandsuper parent(2) 28 | -------------------------------------------------------------------------------- /GrandSuper/GrandSuper/DDSuperProxy.m: -------------------------------------------------------------------------------- 1 | // 2 | // DDSuperProxy.m 3 | // GrandSuper 4 | // 5 | // Created by Dave DeLong on 12/3/11. 6 | // Copyright (c) 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "DDSuperProxy.h" 10 | #import 11 | 12 | @interface NSInvocation (PrivateMethod) 13 | 14 | - (void)invokeUsingIMP:(IMP)imp; 15 | 16 | @end 17 | 18 | @implementation DDSuperProxy 19 | 20 | - (id)initWithProxy:(id)proxyTarget superLevel:(int)level originalContext:(const char *)oContext { 21 | if ((oContext[0] != '-' && oContext[0] != '+') || 22 | (level < 0) || 23 | (proxyTarget == nil) || 24 | (oContext == NULL)) { 25 | 26 | [self release]; 27 | return nil; 28 | } 29 | 30 | const char* classNameStr = oContext+2; // +2 to skip the -[ or +[ 31 | NSString *tmp = [NSString stringWithCString:classNameStr encoding:NSUTF8StringEncoding]; 32 | NSRange r = [tmp rangeOfString:@" "]; 33 | NSString *className = [tmp substringToIndex:r.location]; 34 | 35 | NSLog(@"executing in context: %@", className); 36 | 37 | if (oContext[0] == '+') { 38 | _context = objc_getMetaClass([className UTF8String]); 39 | } else { 40 | _context = objc_getClass([className UTF8String]); 41 | } 42 | 43 | if (_context == nil) { 44 | [self release]; 45 | return nil; 46 | } 47 | 48 | _level = level; 49 | _target = [proxyTarget retain]; 50 | return self; 51 | } 52 | 53 | - (void)dealloc { 54 | [_target release]; 55 | [super dealloc]; 56 | } 57 | 58 | - (NSMethodSignature *)methodSignatureForSelector:(SEL)sel { 59 | return [_target methodSignatureForSelector:sel]; 60 | } 61 | 62 | - (IMP)impForSelector:(SEL)selector { 63 | Class currentClass = _context; 64 | IMP imp = NULL; 65 | int level = -1; 66 | while (level != _level && currentClass != nil) { 67 | IMP thisImp = class_getMethodImplementation(currentClass, selector); 68 | currentClass = class_getSuperclass(currentClass); 69 | if (imp != thisImp) { 70 | imp = thisImp; 71 | level++; 72 | } 73 | } 74 | 75 | return imp; 76 | } 77 | 78 | - (void)forwardInvocation:(NSInvocation *)invocation { 79 | if (![_target respondsToSelector:[invocation selector]]) { 80 | [_target doesNotRecognizeSelector:[invocation selector]]; 81 | return; 82 | } 83 | 84 | IMP appropriateImp = [self impForSelector:[invocation selector]]; 85 | if (appropriateImp != NULL) { 86 | [invocation invokeUsingIMP:appropriateImp]; 87 | } 88 | } 89 | 90 | @end 91 | -------------------------------------------------------------------------------- /GrandSuper/GrandSuper/GrandSuper-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'GrandSuper' target in the 'GrandSuper' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /GrandSuper/GrandSuper/GrandSuper.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 12/3/11 \" DATE 7 | .Dt GrandSuper 1 \" Program name and manual section number 8 | .Os Darwin 9 | .Sh NAME \" Section Header - required - don't modify 10 | .Nm GrandSuper, 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 -------------------------------------------------------------------------------- /GrandSuper/GrandSuper/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // GrandSuper 4 | // 5 | // Created by Dave DeLong on 12/3/11. 6 | // Copyright (c) 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "DDSuperProxy.h" 11 | @interface A : NSObject @end 12 | @implementation A 13 | 14 | - (void)doFoo { 15 | NSLog(@"%s", __PRETTY_FUNCTION__); 16 | } 17 | 18 | @end 19 | 20 | @interface B : A @end 21 | @implementation B 22 | 23 | - (void)doFoo { 24 | NSLog(@"%s", __PRETTY_FUNCTION__); 25 | [super doFoo]; 26 | } 27 | 28 | @end 29 | 30 | @interface C : B @end 31 | @implementation C 32 | 33 | - (void)doFoo { 34 | NSLog(@"%s", __PRETTY_FUNCTION__); 35 | [super doFoo]; 36 | } 37 | 38 | @end 39 | 40 | @interface D : C @end 41 | @implementation D 42 | 43 | - (void)doFoo { 44 | NSLog(@"%s", __PRETTY_FUNCTION__); 45 | [grandsuper doFoo]; 46 | } 47 | 48 | @end 49 | 50 | @interface E : D @end 51 | @implementation E 52 | 53 | - (void)doFoo { 54 | NSLog(@"%s", __PRETTY_FUNCTION__); 55 | 56 | // parent(3) = B's implementation of doFoo 57 | // parent(0) = self 58 | // parent(1) = D 59 | // parent(2) = C 60 | // parent(3) = B 61 | [parent(3) doFoo]; 62 | } 63 | 64 | @end 65 | 66 | int main (int argc, const char * argv[]) 67 | { 68 | 69 | @autoreleasepool { 70 | 71 | E *e = [[E alloc] init]; 72 | [e doFoo]; 73 | [e release]; 74 | 75 | } 76 | return 0; 77 | } 78 | 79 | -------------------------------------------------------------------------------- /JoinPoints/JoinPoints.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 55472748147EE7A500533F18 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 55472747147EE7A500533F18 /* Foundation.framework */; }; 11 | 5547274B147EE7A500533F18 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 5547274A147EE7A500533F18 /* main.m */; }; 12 | 5547274F147EE7A500533F18 /* JoinPoints.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = 5547274E147EE7A500533F18 /* JoinPoints.1 */; }; 13 | 55472757147EE7BC00533F18 /* NSObject+JoinPoints.m in Sources */ = {isa = PBXBuildFile; fileRef = 55472756147EE7BC00533F18 /* NSObject+JoinPoints.m */; }; 14 | B11F560714E574A300B1718F /* ForwardingClass.m in Sources */ = {isa = PBXBuildFile; fileRef = B11F560614E574A300B1718F /* ForwardingClass.m */; }; 15 | /* End PBXBuildFile section */ 16 | 17 | /* Begin PBXCopyFilesBuildPhase section */ 18 | 55472741147EE7A500533F18 /* CopyFiles */ = { 19 | isa = PBXCopyFilesBuildPhase; 20 | buildActionMask = 2147483647; 21 | dstPath = /usr/share/man/man1/; 22 | dstSubfolderSpec = 0; 23 | files = ( 24 | 5547274F147EE7A500533F18 /* JoinPoints.1 in CopyFiles */, 25 | ); 26 | runOnlyForDeploymentPostprocessing = 1; 27 | }; 28 | /* End PBXCopyFilesBuildPhase section */ 29 | 30 | /* Begin PBXFileReference section */ 31 | 55472743147EE7A500533F18 /* JoinPoints */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = JoinPoints; sourceTree = BUILT_PRODUCTS_DIR; }; 32 | 55472747147EE7A500533F18 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 33 | 5547274A147EE7A500533F18 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 34 | 5547274D147EE7A500533F18 /* JoinPoints-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "JoinPoints-Prefix.pch"; sourceTree = ""; }; 35 | 5547274E147EE7A500533F18 /* JoinPoints.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = JoinPoints.1; sourceTree = ""; }; 36 | 55472755147EE7BC00533F18 /* NSObject+JoinPoints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+JoinPoints.h"; sourceTree = ""; }; 37 | 55472756147EE7BC00533F18 /* NSObject+JoinPoints.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+JoinPoints.m"; sourceTree = ""; }; 38 | B11F560514E574A300B1718F /* ForwardingClass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ForwardingClass.h; sourceTree = ""; }; 39 | B11F560614E574A300B1718F /* ForwardingClass.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ForwardingClass.m; sourceTree = ""; }; 40 | /* End PBXFileReference section */ 41 | 42 | /* Begin PBXFrameworksBuildPhase section */ 43 | 55472740147EE7A500533F18 /* Frameworks */ = { 44 | isa = PBXFrameworksBuildPhase; 45 | buildActionMask = 2147483647; 46 | files = ( 47 | 55472748147EE7A500533F18 /* Foundation.framework in Frameworks */, 48 | ); 49 | runOnlyForDeploymentPostprocessing = 0; 50 | }; 51 | /* End PBXFrameworksBuildPhase section */ 52 | 53 | /* Begin PBXGroup section */ 54 | 55472738147EE7A400533F18 = { 55 | isa = PBXGroup; 56 | children = ( 57 | 55472749147EE7A500533F18 /* JoinPoints */, 58 | 55472746147EE7A500533F18 /* Frameworks */, 59 | 55472744147EE7A500533F18 /* Products */, 60 | ); 61 | sourceTree = ""; 62 | }; 63 | 55472744147EE7A500533F18 /* Products */ = { 64 | isa = PBXGroup; 65 | children = ( 66 | 55472743147EE7A500533F18 /* JoinPoints */, 67 | ); 68 | name = Products; 69 | sourceTree = ""; 70 | }; 71 | 55472746147EE7A500533F18 /* Frameworks */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | 55472747147EE7A500533F18 /* Foundation.framework */, 75 | ); 76 | name = Frameworks; 77 | sourceTree = ""; 78 | }; 79 | 55472749147EE7A500533F18 /* JoinPoints */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | 5547274A147EE7A500533F18 /* main.m */, 83 | 55472755147EE7BC00533F18 /* NSObject+JoinPoints.h */, 84 | 55472756147EE7BC00533F18 /* NSObject+JoinPoints.m */, 85 | B11F560514E574A300B1718F /* ForwardingClass.h */, 86 | B11F560614E574A300B1718F /* ForwardingClass.m */, 87 | 5547274E147EE7A500533F18 /* JoinPoints.1 */, 88 | 5547274C147EE7A500533F18 /* Supporting Files */, 89 | ); 90 | path = JoinPoints; 91 | sourceTree = ""; 92 | }; 93 | 5547274C147EE7A500533F18 /* Supporting Files */ = { 94 | isa = PBXGroup; 95 | children = ( 96 | 5547274D147EE7A500533F18 /* JoinPoints-Prefix.pch */, 97 | ); 98 | name = "Supporting Files"; 99 | sourceTree = ""; 100 | }; 101 | /* End PBXGroup section */ 102 | 103 | /* Begin PBXNativeTarget section */ 104 | 55472742147EE7A500533F18 /* JoinPoints */ = { 105 | isa = PBXNativeTarget; 106 | buildConfigurationList = 55472752147EE7A500533F18 /* Build configuration list for PBXNativeTarget "JoinPoints" */; 107 | buildPhases = ( 108 | 5547273F147EE7A500533F18 /* Sources */, 109 | 55472740147EE7A500533F18 /* Frameworks */, 110 | 55472741147EE7A500533F18 /* CopyFiles */, 111 | ); 112 | buildRules = ( 113 | ); 114 | dependencies = ( 115 | ); 116 | name = JoinPoints; 117 | productName = JoinPoints; 118 | productReference = 55472743147EE7A500533F18 /* JoinPoints */; 119 | productType = "com.apple.product-type.tool"; 120 | }; 121 | /* End PBXNativeTarget section */ 122 | 123 | /* Begin PBXProject section */ 124 | 5547273A147EE7A400533F18 /* Project object */ = { 125 | isa = PBXProject; 126 | attributes = { 127 | LastUpgradeCheck = 0430; 128 | }; 129 | buildConfigurationList = 5547273D147EE7A400533F18 /* Build configuration list for PBXProject "JoinPoints" */; 130 | compatibilityVersion = "Xcode 3.2"; 131 | developmentRegion = English; 132 | hasScannedForEncodings = 0; 133 | knownRegions = ( 134 | en, 135 | ); 136 | mainGroup = 55472738147EE7A400533F18; 137 | productRefGroup = 55472744147EE7A500533F18 /* Products */; 138 | projectDirPath = ""; 139 | projectRoot = ""; 140 | targets = ( 141 | 55472742147EE7A500533F18 /* JoinPoints */, 142 | ); 143 | }; 144 | /* End PBXProject section */ 145 | 146 | /* Begin PBXSourcesBuildPhase section */ 147 | 5547273F147EE7A500533F18 /* Sources */ = { 148 | isa = PBXSourcesBuildPhase; 149 | buildActionMask = 2147483647; 150 | files = ( 151 | 5547274B147EE7A500533F18 /* main.m in Sources */, 152 | 55472757147EE7BC00533F18 /* NSObject+JoinPoints.m in Sources */, 153 | B11F560714E574A300B1718F /* ForwardingClass.m in Sources */, 154 | ); 155 | runOnlyForDeploymentPostprocessing = 0; 156 | }; 157 | /* End PBXSourcesBuildPhase section */ 158 | 159 | /* Begin XCBuildConfiguration section */ 160 | 55472750147EE7A500533F18 /* Debug */ = { 161 | isa = XCBuildConfiguration; 162 | buildSettings = { 163 | ALWAYS_SEARCH_USER_PATHS = NO; 164 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 165 | COPY_PHASE_STRIP = NO; 166 | GCC_C_LANGUAGE_STANDARD = gnu99; 167 | GCC_DYNAMIC_NO_PIC = NO; 168 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 169 | GCC_OPTIMIZATION_LEVEL = 0; 170 | GCC_PREPROCESSOR_DEFINITIONS = ( 171 | "DEBUG=1", 172 | "$(inherited)", 173 | ); 174 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 175 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 176 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 177 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 178 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 179 | GCC_WARN_UNUSED_VARIABLE = YES; 180 | MACOSX_DEPLOYMENT_TARGET = 10.7; 181 | ONLY_ACTIVE_ARCH = YES; 182 | SDKROOT = macosx; 183 | }; 184 | name = Debug; 185 | }; 186 | 55472751147EE7A500533F18 /* Release */ = { 187 | isa = XCBuildConfiguration; 188 | buildSettings = { 189 | ALWAYS_SEARCH_USER_PATHS = NO; 190 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 191 | COPY_PHASE_STRIP = YES; 192 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 193 | GCC_C_LANGUAGE_STANDARD = gnu99; 194 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 195 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 196 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 197 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 198 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 199 | GCC_WARN_UNUSED_VARIABLE = YES; 200 | MACOSX_DEPLOYMENT_TARGET = 10.7; 201 | SDKROOT = macosx; 202 | }; 203 | name = Release; 204 | }; 205 | 55472753147EE7A500533F18 /* Debug */ = { 206 | isa = XCBuildConfiguration; 207 | buildSettings = { 208 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 209 | GCC_PREFIX_HEADER = "JoinPoints/JoinPoints-Prefix.pch"; 210 | PRODUCT_NAME = "$(TARGET_NAME)"; 211 | }; 212 | name = Debug; 213 | }; 214 | 55472754147EE7A500533F18 /* Release */ = { 215 | isa = XCBuildConfiguration; 216 | buildSettings = { 217 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 218 | GCC_PREFIX_HEADER = "JoinPoints/JoinPoints-Prefix.pch"; 219 | PRODUCT_NAME = "$(TARGET_NAME)"; 220 | }; 221 | name = Release; 222 | }; 223 | /* End XCBuildConfiguration section */ 224 | 225 | /* Begin XCConfigurationList section */ 226 | 5547273D147EE7A400533F18 /* Build configuration list for PBXProject "JoinPoints" */ = { 227 | isa = XCConfigurationList; 228 | buildConfigurations = ( 229 | 55472750147EE7A500533F18 /* Debug */, 230 | 55472751147EE7A500533F18 /* Release */, 231 | ); 232 | defaultConfigurationIsVisible = 0; 233 | defaultConfigurationName = Release; 234 | }; 235 | 55472752147EE7A500533F18 /* Build configuration list for PBXNativeTarget "JoinPoints" */ = { 236 | isa = XCConfigurationList; 237 | buildConfigurations = ( 238 | 55472753147EE7A500533F18 /* Debug */, 239 | 55472754147EE7A500533F18 /* Release */, 240 | ); 241 | defaultConfigurationIsVisible = 0; 242 | defaultConfigurationName = Release; 243 | }; 244 | /* End XCConfigurationList section */ 245 | }; 246 | rootObject = 5547273A147EE7A400533F18 /* Project object */; 247 | } 248 | -------------------------------------------------------------------------------- /JoinPoints/JoinPoints.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /JoinPoints/JoinPoints/ForwardingClass.h: -------------------------------------------------------------------------------- 1 | // 2 | // ForwardingClass.h 3 | // JoinPoints 4 | // 5 | // Created by Jim Turner on 2/10/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ForwardingClass : NSObject 12 | -(void) aMethod; 13 | @end 14 | -------------------------------------------------------------------------------- /JoinPoints/JoinPoints/ForwardingClass.m: -------------------------------------------------------------------------------- 1 | // 2 | // ForwardingClass.m 3 | // JoinPoints 4 | // 5 | // Created by Jim Turner on 2/10/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "ForwardingClass.h" 10 | 11 | @interface PrivateInternalClass : NSObject 12 | @end 13 | 14 | @interface ForwardingClass () 15 | { 16 | PrivateInternalClass *_internal; 17 | } 18 | @end 19 | 20 | @implementation ForwardingClass 21 | 22 | -(id) init { 23 | self = [super init]; 24 | if( self != nil ){ 25 | _internal = [[PrivateInternalClass alloc] init]; 26 | } 27 | 28 | return( self ); 29 | } 30 | 31 | -(void) aMethod { 32 | NSLog(@"%s", __PRETTY_FUNCTION__); 33 | } 34 | 35 | -(NSMethodSignature *) methodSignatureForSelector:(SEL)selector { 36 | NSMethodSignature *methodSignature = [super methodSignatureForSelector:selector]; 37 | if( !methodSignature ) { 38 | methodSignature = [_internal methodSignatureForSelector:selector]; 39 | } 40 | 41 | return( methodSignature ); 42 | } 43 | 44 | -(void) forwardInvocation:(NSInvocation *)invocation { 45 | [invocation setTarget:_internal]; 46 | [invocation invoke]; 47 | } 48 | 49 | @end 50 | 51 | 52 | @implementation PrivateInternalClass 53 | 54 | -(void) voodooMethod { 55 | NSLog(@"%s", __PRETTY_FUNCTION__); 56 | } 57 | 58 | @end -------------------------------------------------------------------------------- /JoinPoints/JoinPoints/JoinPoints-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'JoinPoints' target in the 'JoinPoints' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /JoinPoints/JoinPoints/JoinPoints.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 11/24/11 \" DATE 7 | .Dt JoinPoints 1 \" Program name and manual section number 8 | .Os Darwin 9 | .Sh NAME \" Section Header - required - don't modify 10 | .Nm JoinPoints, 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 -------------------------------------------------------------------------------- /JoinPoints/JoinPoints/NSObject+JoinPoints.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+JoinPoints.h 3 | // JoinPoints 4 | // 5 | // Created by Dave DeLong on 11/24/11. 6 | // Copyright (c) 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSObject (JoinPoints) 12 | 13 | /** 14 | 15 | Calling these on instances will cause the blocks to be run only when that particular instance receives the designated message. 16 | Calling these on classes will cause the blocks to be run when any instance receives the designated message. 17 | Does not work on class methods. 18 | 19 | **/ 20 | - (void)before:(SEL)selector do:(dispatch_block_t)block; 21 | - (void)during:(SEL)selector do:(dispatch_block_t)block; // block is executed on a background queue 22 | - (void)after:(SEL)selector do:(dispatch_block_t)block; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /JoinPoints/JoinPoints/NSObject+JoinPoints.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+JoinPoints.m 3 | // JoinPoints 4 | // 5 | // Created by Dave DeLong on 11/24/11. 6 | // Copyright (c) 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "NSObject+JoinPoints.h" 10 | #import 11 | #import 12 | 13 | static char JP_BeforeBlocks; 14 | static char JP_DuringBlocks; 15 | static char JP_AfterBlocks; 16 | 17 | static NSArray* JP_GetBlocks(id self, SEL _cmd, const void *key); 18 | 19 | typedef struct { 20 | Class klass; 21 | IMP forwardInvocationImp; 22 | IMP methodSignatureForSelectorImp; 23 | } ClassOriginalForwardingInfo; 24 | typedef ClassOriginalForwardingInfo *ClassOriginalForwardingInfoPtr; 25 | 26 | static ClassOriginalForwardingInfoPtr originalClassForwardingInfo = NULL; 27 | static int originalClassForwardingInfoIndex = 0; 28 | static IMP originalForwardInvocationImp = NULL; 29 | 30 | // given a selector, this returns a new selector that corresponds to the "shadow" method 31 | static SEL JP_SelectorMunge(SEL selector) { 32 | return NSSelectorFromString([NSString stringWithFormat:@"JP_%@", NSStringFromSelector(selector)]); 33 | } 34 | 35 | // Returns the appropriate signature for a method from a class that's over-ridden forwardInvocation: and methodSignatureForSelector: 36 | static NSMethodSignature *nsobject_methodSignatureForSelector(id self, SEL _cmd, SEL selector) { 37 | int x; 38 | NSMethodSignature *signature = nil; 39 | SEL mungedSelector = JP_SelectorMunge(selector); 40 | Class thisClass = object_getClass(self); 41 | IMP originalMethodSignatureForSelectorImp = NULL; 42 | 43 | for( x=0; x<=originalClassForwardingInfoIndex; x++ ) { 44 | ClassOriginalForwardingInfo info = originalClassForwardingInfo[x]; 45 | if( info.klass == thisClass ) { 46 | if( info.methodSignatureForSelectorImp != NULL ) { 47 | originalMethodSignatureForSelectorImp = info.methodSignatureForSelectorImp; 48 | } 49 | 50 | if( class_getInstanceMethod(thisClass, mungedSelector) || class_getClassMethod(thisClass, mungedSelector) ) { 51 | signature = [thisClass instanceMethodSignatureForSelector:mungedSelector]; 52 | } 53 | } 54 | 55 | if( signature ) { 56 | break; 57 | } 58 | } 59 | 60 | // If we found no munged selector, see if the class has an implemetation for this method and get a signature from that. If we can't find an implementation, call the original implementation and return that answer. 61 | if( !signature ) { 62 | if( class_getInstanceMethod(thisClass, selector) || class_getClassMethod(thisClass, selector) ) { 63 | signature = [thisClass instanceMethodSignatureForSelector:selector]; 64 | } 65 | 66 | if( !signature ) { 67 | NSAssert( originalMethodSignatureForSelectorImp != NULL, @"originalMethodSignatureForSelectorImp is NULL... that's bad"); 68 | signature = originalMethodSignatureForSelectorImp(self, _cmd, selector); 69 | } 70 | } 71 | 72 | return( signature ); 73 | } 74 | 75 | // this is the heart of the code. here is where we invoke the blocks and run the original method 76 | static void nsobject_forwardInvocation(id self, SEL _cmd, NSInvocation *invocation) { 77 | // at this point, we have the invocation 78 | // TODO: WHAT DO WE DO WITH IT?? 79 | // NSLog(@"we found this invocation: %@", invocation); 80 | 81 | // It is entirely possible to get here legimitately (e.g., a class depends on forwardInvocation: to communicate to a private class). If we can't find a munged selector, we need to invoke the original forwardInvocation: and send the message on its way. 82 | SEL selector = [invocation selector]; 83 | SEL mungedSelector = JP_SelectorMunge(selector); 84 | if( !class_getInstanceMethod(object_getClass(self), mungedSelector) && !class_getClassMethod(object_getClass(self), mungedSelector) ) { 85 | if( originalClassForwardingInfo != NULL ) { 86 | int x; 87 | for( x=0; x<=originalClassForwardingInfoIndex; x++ ) { 88 | ClassOriginalForwardingInfo info = originalClassForwardingInfo[x]; 89 | if( info.klass == object_getClass(self) ) { 90 | // Forwarding to class original forwardInvocation: 91 | info.forwardInvocationImp(self, _cmd, invocation); 92 | return; 93 | } 94 | } 95 | } 96 | 97 | // forwarding to NSObject original forwardInvocation: 98 | originalForwardInvocationImp(self, _cmd, invocation); 99 | return; 100 | } 101 | 102 | NSArray *before = JP_GetBlocks(self, selector, &JP_BeforeBlocks); 103 | NSArray *during = JP_GetBlocks(self, selector, &JP_DuringBlocks); 104 | NSArray *after = JP_GetBlocks(self, selector, &JP_AfterBlocks); 105 | 106 | for (id block in before) { 107 | dispatch_block_t b = block; 108 | b(); 109 | } 110 | 111 | //alter the selector to point to the shadow methods 112 | [invocation setSelector:mungedSelector]; 113 | 114 | dispatch_group_t group = dispatch_group_create(); 115 | for (id block in during) { 116 | dispatch_group_async(group, dispatch_get_global_queue(0, 0), block); 117 | } 118 | [invocation invoke]; 119 | dispatch_group_wait(group, DISPATCH_TIME_FOREVER); 120 | dispatch_release(group); 121 | 122 | for (id block in after) { 123 | dispatch_block_t b = block; 124 | b(); 125 | } 126 | 127 | } 128 | 129 | // we have to replace -[NSObject forwardInvocation:] with our own version 130 | // the original implementation calls -doesNotRecognizeSelector: 131 | // when the invocation is invoked, it will call -doesNotRecognizeSelector: if invocation fails 132 | static void JP_InstallNSObjectForwardInvocationReplacement(void) { 133 | static dispatch_once_t onceToken; 134 | dispatch_once(&onceToken, ^{ 135 | Class nsobject = objc_getClass("NSObject"); 136 | if (!nsobject) { return; } 137 | 138 | SEL forwardInvocation = @selector(forwardInvocation:); 139 | originalForwardInvocationImp = class_replaceMethod(nsobject, forwardInvocation, (IMP)nsobject_forwardInvocation, "v@:@"); 140 | }); 141 | } 142 | 143 | // save the block that we want to run 144 | static void JP_AddBlock(id self, SEL _cmd, const void *key, dispatch_block_t block) { 145 | if (block == nil) { return; } 146 | 147 | NSMutableDictionary *mappings = objc_getAssociatedObject(self, key); 148 | if (mappings == nil) { 149 | mappings = [NSMutableDictionary dictionary]; 150 | objc_setAssociatedObject(self, key, mappings, OBJC_ASSOCIATION_RETAIN); 151 | } 152 | NSMutableArray *blocksForSelector = [mappings objectForKey:NSStringFromSelector(_cmd)]; 153 | if (blocksForSelector == nil) { 154 | blocksForSelector = [NSMutableArray array]; 155 | [mappings setObject:blocksForSelector forKey:NSStringFromSelector(_cmd)]; 156 | } 157 | 158 | block = Block_copy(block); 159 | [blocksForSelector addObject:block]; 160 | Block_release(block); 161 | } 162 | 163 | // get all the blocks that correspond to a particular selector 164 | static NSArray* JP_GetBlocks(id self, SEL _cmd, const void *key) { 165 | NSMutableArray *blocks = [NSMutableArray array]; 166 | 167 | if (self) { 168 | NSDictionary *mappings = objc_getAssociatedObject(self, key); 169 | NSArray *blocksForSelector = [mappings objectForKey:NSStringFromSelector(_cmd)]; 170 | if (blocksForSelector) { 171 | [blocks addObjectsFromArray:blocksForSelector]; 172 | } 173 | 174 | Class isa = object_getClass(self); 175 | if (class_isMetaClass(isa)) { 176 | // self was a Class already 177 | // walk up the superclass chain 178 | [blocks addObjectsFromArray:JP_GetBlocks(class_getSuperclass(self), _cmd, key)]; 179 | } else { 180 | // self was an instance 181 | [blocks addObjectsFromArray:JP_GetBlocks(isa, _cmd, key)]; 182 | } 183 | } 184 | return blocks; 185 | } 186 | 187 | // move the original method aside as a "shadow" 188 | static void JP_Shadow(Class self, SEL _cmd) { 189 | if (self == nil) { return; } 190 | 191 | NSMethodSignature *sig = [self instanceMethodSignatureForSelector:_cmd]; 192 | 193 | IMP forwardingIMP = _objc_msgForward; 194 | if ([sig methodReturnLength] > sizeof(id)) { 195 | // gotta use the _stret stuff 196 | forwardingIMP = (IMP)_objc_msgForward_stret; 197 | } 198 | 199 | SEL shadowedSel = JP_SelectorMunge(_cmd); 200 | Method m = class_getInstanceMethod(self, _cmd); 201 | // If the class does not implement the method, we shouldn't add an implementation 202 | if (m && method_getImplementation(m) != forwardingIMP) { 203 | class_addMethod(self, shadowedSel, method_getImplementation(m), method_getTypeEncoding(m)); 204 | method_setImplementation(m, forwardingIMP); 205 | } 206 | 207 | SEL forwardInvocation = @selector(forwardInvocation:); 208 | if( [self instancesRespondToSelector:forwardInvocation] && 209 | (class_getMethodImplementation(self, forwardInvocation) != (IMP)nsobject_forwardInvocation) ) { 210 | 211 | IMP classOriginalForwardInvocationImp = class_replaceMethod(self, forwardInvocation, (IMP)nsobject_forwardInvocation, "v@:@"); 212 | 213 | ClassOriginalForwardingInfo info; 214 | info.klass = self; 215 | info.forwardInvocationImp = classOriginalForwardInvocationImp; 216 | 217 | SEL methodSignatureForSelector = @selector(methodSignatureForSelector:); 218 | if( [self instancesRespondToSelector:methodSignatureForSelector] ) { 219 | info.methodSignatureForSelectorImp = class_replaceMethod(self, methodSignatureForSelector, (IMP)nsobject_methodSignatureForSelector, "@@::"); 220 | } 221 | 222 | if( originalClassForwardingInfo == NULL ) { 223 | originalClassForwardingInfo = malloc( sizeof(ClassOriginalForwardingInfo) ); 224 | memcpy(originalClassForwardingInfo, &info, sizeof(ClassOriginalForwardingInfo)); 225 | } 226 | else { 227 | originalClassForwardingInfoIndex++; 228 | originalClassForwardingInfo = realloc(originalClassForwardingInfo, originalClassForwardingInfoIndex+1); 229 | memcpy(&originalClassForwardingInfo[originalClassForwardingInfoIndex], &info, sizeof(ClassOriginalForwardingInfo)); 230 | } 231 | } 232 | 233 | JP_Shadow(class_getSuperclass(self), _cmd); 234 | } 235 | 236 | // there are some methods we won't touch 237 | static BOOL JP_IsSafeSelector(SEL _cmd) { 238 | // messing with memory management is asking for trouble 239 | if (_cmd == @selector(retain)) { return NO; } 240 | if (_cmd == @selector(release)) { return NO; } 241 | if (_cmd == @selector(autorelease)) { return NO; } 242 | if (_cmd == @selector(dealloc)) { return NO; } 243 | 244 | // for safety, don't mess with anything that POCOs respond to 245 | return ![NSObject instancesRespondToSelector:_cmd]; 246 | } 247 | 248 | static void JP_InstallJoinPoint(id self, SEL _cmd, const void *key, dispatch_block_t block) { 249 | if (JP_IsSafeSelector(_cmd) && block != nil) { 250 | JP_InstallNSObjectForwardInvocationReplacement(); 251 | JP_AddBlock(self, _cmd, key, block); 252 | 253 | Class c = object_getClass(self); 254 | if (class_isMetaClass(c)) { c = (Class)self; } 255 | JP_Shadow(c, _cmd); 256 | } 257 | } 258 | 259 | @implementation NSObject (JoinPoints) 260 | 261 | - (void)before:(SEL)selector do:(dispatch_block_t)block { 262 | JP_InstallJoinPoint(self, selector, &JP_BeforeBlocks, block); 263 | } 264 | 265 | - (void)during:(SEL)selector do:(dispatch_block_t)block { 266 | JP_InstallJoinPoint(self, selector, &JP_DuringBlocks, block); 267 | } 268 | 269 | - (void)after:(SEL)selector do:(dispatch_block_t)block { 270 | JP_InstallJoinPoint(self, selector, &JP_AfterBlocks, block); 271 | } 272 | 273 | @end 274 | -------------------------------------------------------------------------------- /JoinPoints/JoinPoints/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // JoinPoints 4 | // 5 | // Created by Dave DeLong on 11/24/11. 6 | // Copyright (c) 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "NSObject+JoinPoints.h" 11 | #import "ForwardingClass.h" 12 | 13 | typedef struct { 14 | NSInteger a; 15 | CGFloat b; 16 | NSString *c; 17 | } LongStruct; 18 | 19 | @interface A : NSObject 20 | @end 21 | @implementation A 22 | 23 | - (void)doFoo:(NSString *)foo { 24 | NSLog(@"%s", __PRETTY_FUNCTION__); 25 | } 26 | 27 | - (LongStruct)doBar:(LongStruct)s { 28 | s.a *= 2; 29 | s.b *= 2.0f; 30 | s.c = [NSString stringWithFormat:@"JP_%@", s.c]; 31 | return s; 32 | } 33 | 34 | @end 35 | 36 | @interface B : A 37 | @end 38 | @implementation B 39 | 40 | - (void)doFoo:(NSString *)foo { 41 | NSLog(@"%s", __PRETTY_FUNCTION__); 42 | [super doFoo:foo]; 43 | } 44 | 45 | @end 46 | 47 | int main (int argc, const char * argv[]) 48 | { 49 | 50 | @autoreleasepool { 51 | NSLog(@" "); 52 | 53 | [A before:@selector(doFoo:) do:^{ 54 | NSLog(@"before"); 55 | }]; 56 | [A during:@selector(doFoo:) do:^{ 57 | NSLog(@"during"); 58 | }]; 59 | [A after:@selector(doFoo:) do:^{ 60 | NSLog(@"after"); 61 | }]; 62 | 63 | // uncommenting this currently causes an infinite loop 64 | // [B before:@selector(doFoo:) do:^{ 65 | // NSLog(@"b before"); 66 | // }]; 67 | 68 | [A before:@selector(dealloc) do:^{ 69 | NSLog(@"dealloc!"); 70 | }]; 71 | 72 | LongStruct s; 73 | s.a = 21; 74 | s.b = 42; 75 | s.c = @"Tricky!"; 76 | 77 | [A before:@selector(doBar:) do:^{ 78 | NSLog(@"before doBar:"); 79 | }]; 80 | 81 | A *a = [A new]; 82 | [a before:@selector(doFoo:) do:^{ 83 | NSLog(@"this is specific to this instance"); 84 | }]; 85 | [a doFoo:@"blah"]; 86 | 87 | NSLog(@"=================="); 88 | 89 | NSLog(@"%@", s.c); 90 | s = [a doBar:s]; 91 | NSLog(@"%@", s.c); 92 | [a release]; 93 | 94 | NSLog(@"=================="); 95 | 96 | B *b = [B new]; 97 | [b doFoo:@"B"]; 98 | 99 | NSLog(@"=================="); 100 | 101 | NSLog(@"%@", s.c); 102 | s = [b doBar:s]; 103 | NSLog(@"%@", s.c); 104 | 105 | [b release]; 106 | 107 | NSLog(@"=================="); 108 | [ForwardingClass before:@selector(aMethod) do:^{ 109 | NSLog(@"before aMethod"); 110 | }]; 111 | 112 | [ForwardingClass during:@selector(aMethod) do:^{ 113 | NSLog(@"during aMethod"); 114 | }]; 115 | 116 | [ForwardingClass after:@selector(aMethod) do:^{ 117 | NSLog(@"after aMethod"); 118 | }]; 119 | 120 | // Attempting to shim a method a class does not implement does nothing 121 | [ForwardingClass before:@selector(voodooMethod) do:^{ 122 | NSLog(@"before voodooMethod"); 123 | }]; 124 | 125 | ForwardingClass *fc = [ForwardingClass new]; 126 | [fc aMethod]; 127 | 128 | [fc performSelector:@selector(voodooMethod)]; 129 | } 130 | return 0; 131 | } 132 | 133 | -------------------------------------------------------------------------------- /OlympicRings/OlympicRings-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIconFile 12 | 13 | CFBundleIdentifier 14 | com.yourcompany.${PRODUCT_NAME:rfc1034identifier} 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | ${PRODUCT_NAME} 19 | CFBundlePackageType 20 | APPL 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | NSMainNibFile~ipad 28 | MainWindow_iPad 29 | UIStatusBarHidden 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /OlympicRings/OlympicRings.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 45; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; 11 | 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; 12 | 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; 13 | 2860E328111B887F00E27156 /* AppDelegate_iPhone.m in Sources */ = {isa = PBXBuildFile; fileRef = 2860E326111B887F00E27156 /* AppDelegate_iPhone.m */; }; 14 | 2860E329111B887F00E27156 /* MainWindow_iPhone.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2860E327111B887F00E27156 /* MainWindow_iPhone.xib */; }; 15 | 2860E32E111B888700E27156 /* AppDelegate_iPad.m in Sources */ = {isa = PBXBuildFile; fileRef = 2860E32C111B888700E27156 /* AppDelegate_iPad.m */; }; 16 | 2860E32F111B888700E27156 /* MainWindow_iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2860E32D111B888700E27156 /* MainWindow_iPad.xib */; }; 17 | 288765FD0DF74451002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765FC0DF74451002DB57D /* CoreGraphics.framework */; }; 18 | 55CC28741267F66300BAEFEE /* RingLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 55CC28731267F66300BAEFEE /* RingLayer.m */; }; 19 | 55CC28761267F67600BAEFEE /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 55CC28751267F67600BAEFEE /* QuartzCore.framework */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXFileReference section */ 23 | 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 24 | 1D6058910D05DD3D006BFB54 /* OlympicRings.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OlympicRings.app; sourceTree = BUILT_PRODUCTS_DIR; }; 25 | 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 26 | 2860E325111B887F00E27156 /* AppDelegate_iPhone.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate_iPhone.h; sourceTree = ""; }; 27 | 2860E326111B887F00E27156 /* AppDelegate_iPhone.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate_iPhone.m; sourceTree = ""; }; 28 | 2860E327111B887F00E27156 /* MainWindow_iPhone.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow_iPhone.xib; sourceTree = ""; }; 29 | 2860E32B111B888700E27156 /* AppDelegate_iPad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate_iPad.h; sourceTree = ""; }; 30 | 2860E32C111B888700E27156 /* AppDelegate_iPad.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate_iPad.m; sourceTree = ""; }; 31 | 2860E32D111B888700E27156 /* MainWindow_iPad.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow_iPad.xib; sourceTree = ""; }; 32 | 288765FC0DF74451002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 33 | 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Shared/main.m; sourceTree = ""; }; 34 | 32CA4F630368D1EE00C91783 /* OlympicRings_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OlympicRings_Prefix.pch; sourceTree = ""; }; 35 | 55CC28721267F66300BAEFEE /* RingLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RingLayer.h; sourceTree = ""; }; 36 | 55CC28731267F66300BAEFEE /* RingLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RingLayer.m; sourceTree = ""; }; 37 | 55CC28751267F67600BAEFEE /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; 38 | 8D1107310486CEB800E47090 /* OlympicRings-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "OlympicRings-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = ""; }; 39 | /* End PBXFileReference section */ 40 | 41 | /* Begin PBXFrameworksBuildPhase section */ 42 | 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { 43 | isa = PBXFrameworksBuildPhase; 44 | buildActionMask = 2147483647; 45 | files = ( 46 | 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, 47 | 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, 48 | 288765FD0DF74451002DB57D /* CoreGraphics.framework in Frameworks */, 49 | 55CC28761267F67600BAEFEE /* QuartzCore.framework in Frameworks */, 50 | ); 51 | runOnlyForDeploymentPostprocessing = 0; 52 | }; 53 | /* End PBXFrameworksBuildPhase section */ 54 | 55 | /* Begin PBXGroup section */ 56 | 19C28FACFE9D520D11CA2CBB /* Products */ = { 57 | isa = PBXGroup; 58 | children = ( 59 | 1D6058910D05DD3D006BFB54 /* OlympicRings.app */, 60 | ); 61 | name = Products; 62 | sourceTree = ""; 63 | }; 64 | 2860E324111B887F00E27156 /* iPhone */ = { 65 | isa = PBXGroup; 66 | children = ( 67 | 2860E325111B887F00E27156 /* AppDelegate_iPhone.h */, 68 | 2860E326111B887F00E27156 /* AppDelegate_iPhone.m */, 69 | 2860E327111B887F00E27156 /* MainWindow_iPhone.xib */, 70 | ); 71 | path = iPhone; 72 | sourceTree = ""; 73 | }; 74 | 2860E32A111B888700E27156 /* iPad */ = { 75 | isa = PBXGroup; 76 | children = ( 77 | 2860E32B111B888700E27156 /* AppDelegate_iPad.h */, 78 | 2860E32C111B888700E27156 /* AppDelegate_iPad.m */, 79 | 2860E32D111B888700E27156 /* MainWindow_iPad.xib */, 80 | ); 81 | path = iPad; 82 | sourceTree = ""; 83 | }; 84 | 28EEBF621118D79A00187D67 /* Shared */ = { 85 | isa = PBXGroup; 86 | children = ( 87 | 8D1107310486CEB800E47090 /* OlympicRings-Info.plist */, 88 | ); 89 | name = Shared; 90 | sourceTree = ""; 91 | }; 92 | 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { 93 | isa = PBXGroup; 94 | children = ( 95 | 2860E32A111B888700E27156 /* iPad */, 96 | 2860E324111B887F00E27156 /* iPhone */, 97 | 28EEBF621118D79A00187D67 /* Shared */, 98 | 29B97315FDCFA39411CA2CEA /* Other Sources */, 99 | 29B97323FDCFA39411CA2CEA /* Frameworks */, 100 | 19C28FACFE9D520D11CA2CBB /* Products */, 101 | 55CC28721267F66300BAEFEE /* RingLayer.h */, 102 | 55CC28731267F66300BAEFEE /* RingLayer.m */, 103 | 55CC28751267F67600BAEFEE /* QuartzCore.framework */, 104 | ); 105 | name = CustomTemplate; 106 | sourceTree = ""; 107 | }; 108 | 29B97315FDCFA39411CA2CEA /* Other Sources */ = { 109 | isa = PBXGroup; 110 | children = ( 111 | 32CA4F630368D1EE00C91783 /* OlympicRings_Prefix.pch */, 112 | 29B97316FDCFA39411CA2CEA /* main.m */, 113 | ); 114 | name = "Other Sources"; 115 | sourceTree = ""; 116 | }; 117 | 29B97323FDCFA39411CA2CEA /* Frameworks */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, 121 | 1D30AB110D05D00D00671497 /* Foundation.framework */, 122 | 288765FC0DF74451002DB57D /* CoreGraphics.framework */, 123 | ); 124 | name = Frameworks; 125 | sourceTree = ""; 126 | }; 127 | /* End PBXGroup section */ 128 | 129 | /* Begin PBXNativeTarget section */ 130 | 1D6058900D05DD3D006BFB54 /* OlympicRings */ = { 131 | isa = PBXNativeTarget; 132 | buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "OlympicRings" */; 133 | buildPhases = ( 134 | 1D60588D0D05DD3D006BFB54 /* Resources */, 135 | 1D60588E0D05DD3D006BFB54 /* Sources */, 136 | 1D60588F0D05DD3D006BFB54 /* Frameworks */, 137 | ); 138 | buildRules = ( 139 | ); 140 | dependencies = ( 141 | ); 142 | name = OlympicRings; 143 | productName = OlympicRings; 144 | productReference = 1D6058910D05DD3D006BFB54 /* OlympicRings.app */; 145 | productType = "com.apple.product-type.application"; 146 | }; 147 | /* End PBXNativeTarget section */ 148 | 149 | /* Begin PBXProject section */ 150 | 29B97313FDCFA39411CA2CEA /* Project object */ = { 151 | isa = PBXProject; 152 | buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "OlympicRings" */; 153 | compatibilityVersion = "Xcode 3.1"; 154 | developmentRegion = English; 155 | hasScannedForEncodings = 1; 156 | knownRegions = ( 157 | English, 158 | Japanese, 159 | French, 160 | German, 161 | ); 162 | mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; 163 | projectDirPath = ""; 164 | projectRoot = ""; 165 | targets = ( 166 | 1D6058900D05DD3D006BFB54 /* OlympicRings */, 167 | ); 168 | }; 169 | /* End PBXProject section */ 170 | 171 | /* Begin PBXResourcesBuildPhase section */ 172 | 1D60588D0D05DD3D006BFB54 /* Resources */ = { 173 | isa = PBXResourcesBuildPhase; 174 | buildActionMask = 2147483647; 175 | files = ( 176 | 2860E329111B887F00E27156 /* MainWindow_iPhone.xib in Resources */, 177 | 2860E32F111B888700E27156 /* MainWindow_iPad.xib in Resources */, 178 | ); 179 | runOnlyForDeploymentPostprocessing = 0; 180 | }; 181 | /* End PBXResourcesBuildPhase section */ 182 | 183 | /* Begin PBXSourcesBuildPhase section */ 184 | 1D60588E0D05DD3D006BFB54 /* Sources */ = { 185 | isa = PBXSourcesBuildPhase; 186 | buildActionMask = 2147483647; 187 | files = ( 188 | 1D60589B0D05DD56006BFB54 /* main.m in Sources */, 189 | 2860E328111B887F00E27156 /* AppDelegate_iPhone.m in Sources */, 190 | 2860E32E111B888700E27156 /* AppDelegate_iPad.m in Sources */, 191 | 55CC28741267F66300BAEFEE /* RingLayer.m in Sources */, 192 | ); 193 | runOnlyForDeploymentPostprocessing = 0; 194 | }; 195 | /* End PBXSourcesBuildPhase section */ 196 | 197 | /* Begin XCBuildConfiguration section */ 198 | 1D6058940D05DD3E006BFB54 /* Debug */ = { 199 | isa = XCBuildConfiguration; 200 | buildSettings = { 201 | ALWAYS_SEARCH_USER_PATHS = NO; 202 | COPY_PHASE_STRIP = NO; 203 | GCC_DYNAMIC_NO_PIC = NO; 204 | GCC_OPTIMIZATION_LEVEL = 0; 205 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 206 | GCC_PREFIX_HEADER = OlympicRings_Prefix.pch; 207 | INFOPLIST_FILE = "OlympicRings-Info.plist"; 208 | PRODUCT_NAME = OlympicRings; 209 | }; 210 | name = Debug; 211 | }; 212 | 1D6058950D05DD3E006BFB54 /* Release */ = { 213 | isa = XCBuildConfiguration; 214 | buildSettings = { 215 | ALWAYS_SEARCH_USER_PATHS = NO; 216 | COPY_PHASE_STRIP = YES; 217 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 218 | GCC_PREFIX_HEADER = OlympicRings_Prefix.pch; 219 | INFOPLIST_FILE = "OlympicRings-Info.plist"; 220 | PRODUCT_NAME = OlympicRings; 221 | VALIDATE_PRODUCT = YES; 222 | }; 223 | name = Release; 224 | }; 225 | C01FCF4F08A954540054247B /* Debug */ = { 226 | isa = XCBuildConfiguration; 227 | buildSettings = { 228 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 229 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 230 | GCC_C_LANGUAGE_STANDARD = c99; 231 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 232 | GCC_WARN_UNUSED_VARIABLE = YES; 233 | PREBINDING = NO; 234 | SDKROOT = iphoneos; 235 | TARGETED_DEVICE_FAMILY = 2; 236 | }; 237 | name = Debug; 238 | }; 239 | C01FCF5008A954540054247B /* Release */ = { 240 | isa = XCBuildConfiguration; 241 | buildSettings = { 242 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 243 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 244 | GCC_C_LANGUAGE_STANDARD = c99; 245 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 246 | GCC_WARN_UNUSED_VARIABLE = YES; 247 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 248 | PREBINDING = NO; 249 | SDKROOT = iphoneos; 250 | TARGETED_DEVICE_FAMILY = "1,2"; 251 | }; 252 | name = Release; 253 | }; 254 | /* End XCBuildConfiguration section */ 255 | 256 | /* Begin XCConfigurationList section */ 257 | 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "OlympicRings" */ = { 258 | isa = XCConfigurationList; 259 | buildConfigurations = ( 260 | 1D6058940D05DD3E006BFB54 /* Debug */, 261 | 1D6058950D05DD3E006BFB54 /* Release */, 262 | ); 263 | defaultConfigurationIsVisible = 0; 264 | defaultConfigurationName = Release; 265 | }; 266 | C01FCF4E08A954540054247B /* Build configuration list for PBXProject "OlympicRings" */ = { 267 | isa = XCConfigurationList; 268 | buildConfigurations = ( 269 | C01FCF4F08A954540054247B /* Debug */, 270 | C01FCF5008A954540054247B /* Release */, 271 | ); 272 | defaultConfigurationIsVisible = 0; 273 | defaultConfigurationName = Release; 274 | }; 275 | /* End XCConfigurationList section */ 276 | }; 277 | rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; 278 | } 279 | -------------------------------------------------------------------------------- /OlympicRings/OlympicRings.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /OlympicRings/OlympicRings_Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'OlympicRings' target in the 'OlympicRings' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #import 8 | #endif 9 | -------------------------------------------------------------------------------- /OlympicRings/RingLayer.h: -------------------------------------------------------------------------------- 1 | // 2 | // RingLayer.h 3 | // OlympicRings 4 | // 5 | // Created by Dave DeLong on 10/14/10. 6 | // Copyright 2010 Home. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface RingLayer : CATextLayer { 13 | 14 | } 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /OlympicRings/RingLayer.m: -------------------------------------------------------------------------------- 1 | // 2 | // RingLayer.m 3 | // OlympicRings 4 | // 5 | // Created by Dave DeLong on 10/14/10. 6 | // Copyright 2010 Home. All rights reserved. 7 | // 8 | 9 | #import "RingLayer.h" 10 | 11 | 12 | @implementation RingLayer 13 | 14 | - (id) init { 15 | if (self = [super init]) { 16 | [self setBackgroundColor:[[UIColor clearColor] CGColor]]; 17 | } 18 | return self; 19 | } 20 | 21 | - (void) drawInContext:(CGContextRef)ctx { 22 | CGFloat lineWidth = 15; 23 | CGRect circleRect = CGRectInset([self bounds], lineWidth, lineWidth); 24 | 25 | CGContextSetStrokeColorWithColor(ctx, [self foregroundColor]); 26 | CGContextSetLineWidth(ctx, lineWidth); 27 | CGContextStrokeEllipseInRect(ctx, circleRect); 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /OlympicRings/Shared/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // OlympicRings 4 | // 5 | // Created by Dave DeLong on 10/14/10. 6 | // Copyright 2010 Home. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) { 12 | 13 | NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 14 | int retVal = UIApplicationMain(argc, argv, nil, nil); 15 | [pool release]; 16 | return retVal; 17 | } 18 | -------------------------------------------------------------------------------- /OlympicRings/iPad/AppDelegate_iPad.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate_iPad.h 3 | // OlympicRings 4 | // 5 | // Created by Dave DeLong on 10/14/10. 6 | // Copyright 2010 Home. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "RingLayer.h" 11 | 12 | @interface AppDelegate_iPad : NSObject { 13 | UIWindow *window; 14 | 15 | NSMutableArray * rings; 16 | 17 | RingLayer * red; 18 | RingLayer * green; 19 | RingLayer * blue; 20 | RingLayer * black; 21 | RingLayer * yellow; 22 | } 23 | 24 | @property (nonatomic, retain) IBOutlet UIWindow *window; 25 | 26 | @end 27 | 28 | -------------------------------------------------------------------------------- /OlympicRings/iPad/AppDelegate_iPad.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate_iPad.m 3 | // OlympicRings 4 | // 5 | // Created by Dave DeLong on 10/14/10. 6 | // Copyright 2010 Home. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate_iPad.h" 10 | #import "RingLayer.h" 11 | 12 | @implementation AppDelegate_iPad 13 | 14 | @synthesize window; 15 | 16 | 17 | #pragma mark - 18 | #pragma mark Application lifecycle 19 | 20 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 21 | 22 | // Override point for customization after application launch. 23 | 24 | [self.window makeKeyAndVisible]; 25 | 26 | CGRect frame = [[self window] frame]; 27 | CGFloat oneThird = frame.size.width/3; 28 | 29 | CGSize ringSize = CGSizeMake(oneThird-30, oneThird-30); 30 | 31 | blue = [RingLayer layer]; 32 | [blue setFrame:CGRectMake(0, 0, ringSize.width, ringSize.height)]; 33 | [blue setForegroundColor:[[UIColor blueColor] CGColor]]; 34 | [[window layer] addSublayer:blue]; 35 | 36 | yellow = [RingLayer layer]; 37 | CGRect y = [blue frame]; 38 | y.origin.x = oneThird/2; 39 | y.origin.y = oneThird/2; 40 | [yellow setFrame:y]; 41 | [yellow setForegroundColor:[[UIColor yellowColor] CGColor]]; 42 | [[window layer] addSublayer:yellow]; 43 | 44 | black = [RingLayer layer]; 45 | CGRect r = [blue frame]; 46 | r.origin.x += oneThird; 47 | [black setFrame:r]; 48 | [black setForegroundColor:[[UIColor blackColor] CGColor]]; 49 | [[window layer] addSublayer:black]; 50 | 51 | green = [RingLayer layer]; 52 | y = [yellow frame]; 53 | y.origin.x += oneThird; 54 | [green setFrame:y]; 55 | [green setForegroundColor:[[UIColor greenColor] CGColor]]; 56 | [[window layer] addSublayer:green]; 57 | 58 | red = [RingLayer layer]; 59 | r = [black frame]; 60 | r.origin.x += oneThird; 61 | [red setFrame:r]; 62 | [red setForegroundColor:[[UIColor redColor] CGColor]]; 63 | [[window layer] addSublayer:red]; 64 | 65 | rings = [[NSMutableArray alloc] initWithObjects:red, green, blue, yellow, black, nil]; 66 | 67 | NSTimer * t = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(doSomething:) userInfo:nil repeats:YES]; 68 | 69 | return YES; 70 | } 71 | 72 | - (CGPoint) randomPoint { 73 | 74 | CGRect windowFrame = [window frame]; 75 | return CGPointMake(arc4random() % (int)windowFrame.size.width, 76 | arc4random() % (int)windowFrame.size.height); 77 | } 78 | 79 | - (void) doSomething:(NSTimer *)timer { 80 | for (CALayer * layer in rings) { 81 | CABasicAnimation * a = [CABasicAnimation animationWithKeyPath:@"position"]; 82 | [a setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]]; 83 | [a setFromValue:[NSValue valueWithCGPoint:[layer position]]]; 84 | [a setToValue:[NSValue valueWithCGPoint:[self randomPoint]]]; 85 | [a setAutoreverses:YES]; 86 | [a setDuration:1.0]; 87 | [layer addAnimation:a forKey:nil]; 88 | } 89 | } 90 | 91 | 92 | - (void)applicationWillResignActive:(UIApplication *)application { 93 | /* 94 | Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 95 | Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 96 | */ 97 | } 98 | 99 | 100 | - (void)applicationDidBecomeActive:(UIApplication *)application { 101 | /* 102 | Restart any tasks that were paused (or not yet started) while the application was inactive. 103 | */ 104 | } 105 | 106 | 107 | - (void)applicationWillTerminate:(UIApplication *)application { 108 | /* 109 | Called when the application is about to terminate. 110 | */ 111 | } 112 | 113 | 114 | #pragma mark - 115 | #pragma mark Memory management 116 | 117 | - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application { 118 | /* 119 | Free up as much memory as possible by purging cached data objects that can be recreated (or reloaded from disk) later. 120 | */ 121 | } 122 | 123 | 124 | - (void)dealloc { 125 | [window release]; 126 | [super dealloc]; 127 | } 128 | 129 | 130 | @end 131 | -------------------------------------------------------------------------------- /OlympicRings/iPad/MainWindow_iPad.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1024 5 | 10D573 6 | 782 7 | 1038.29 8 | 460.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 105 12 | 13 | 14 | YES 15 | 16 | 17 | YES 18 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 19 | 20 | 21 | YES 22 | 23 | YES 24 | 25 | 26 | YES 27 | 28 | 29 | 30 | YES 31 | 32 | IBFilesOwner 33 | IBIPadFramework 34 | 35 | 36 | IBFirstResponder 37 | IBIPadFramework 38 | 39 | 40 | 41 | 292 42 | {768, 1024} 43 | 44 | 1 45 | MSAxIDEAA 46 | 47 | NO 48 | NO 49 | 50 | 2 51 | 52 | IBIPadFramework 53 | YES 54 | 55 | 56 | IBIPadFramework 57 | 58 | 59 | 60 | 61 | YES 62 | 63 | 64 | window 65 | 66 | 67 | 68 | 7 69 | 70 | 71 | 72 | delegate 73 | 74 | 75 | 76 | 8 77 | 78 | 79 | 80 | 81 | YES 82 | 83 | 0 84 | 85 | 86 | 87 | 88 | 89 | -1 90 | 91 | 92 | File's Owner 93 | 94 | 95 | -2 96 | 97 | 98 | 99 | 100 | 2 101 | 102 | 103 | YES 104 | 105 | 106 | 107 | 108 | 6 109 | 110 | 111 | 112 | 113 | 114 | 115 | YES 116 | 117 | YES 118 | -1.CustomClassName 119 | -2.CustomClassName 120 | 2.IBEditorWindowLastContentRect 121 | 2.IBPluginDependency 122 | 6.CustomClassName 123 | 6.IBPluginDependency 124 | 125 | 126 | YES 127 | UIApplication 128 | UIResponder 129 | {{903, 55}, {768, 1024}} 130 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 131 | AppDelegate_iPad 132 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 133 | 134 | 135 | 136 | YES 137 | 138 | 139 | YES 140 | 141 | 142 | 143 | 144 | YES 145 | 146 | 147 | YES 148 | 149 | 150 | 151 | 9 152 | 153 | 154 | 155 | YES 156 | 157 | AppDelegate_iPad 158 | NSObject 159 | 160 | window 161 | UIWindow 162 | 163 | 164 | IBProjectSource 165 | iPad/AppDelegate_iPad.h 166 | 167 | 168 | 169 | 170 | YES 171 | 172 | NSObject 173 | 174 | IBFrameworkSource 175 | Foundation.framework/Headers/NSError.h 176 | 177 | 178 | 179 | NSObject 180 | 181 | IBFrameworkSource 182 | Foundation.framework/Headers/NSFileManager.h 183 | 184 | 185 | 186 | NSObject 187 | 188 | IBFrameworkSource 189 | Foundation.framework/Headers/NSKeyValueCoding.h 190 | 191 | 192 | 193 | NSObject 194 | 195 | IBFrameworkSource 196 | Foundation.framework/Headers/NSKeyValueObserving.h 197 | 198 | 199 | 200 | NSObject 201 | 202 | IBFrameworkSource 203 | Foundation.framework/Headers/NSKeyedArchiver.h 204 | 205 | 206 | 207 | NSObject 208 | 209 | IBFrameworkSource 210 | Foundation.framework/Headers/NSObject.h 211 | 212 | 213 | 214 | NSObject 215 | 216 | IBFrameworkSource 217 | Foundation.framework/Headers/NSRunLoop.h 218 | 219 | 220 | 221 | NSObject 222 | 223 | IBFrameworkSource 224 | Foundation.framework/Headers/NSThread.h 225 | 226 | 227 | 228 | NSObject 229 | 230 | IBFrameworkSource 231 | Foundation.framework/Headers/NSURL.h 232 | 233 | 234 | 235 | NSObject 236 | 237 | IBFrameworkSource 238 | Foundation.framework/Headers/NSURLConnection.h 239 | 240 | 241 | 242 | NSObject 243 | 244 | IBFrameworkSource 245 | UIKit.framework/Headers/UIAccessibility.h 246 | 247 | 248 | 249 | NSObject 250 | 251 | IBFrameworkSource 252 | UIKit.framework/Headers/UINibLoading.h 253 | 254 | 255 | 256 | NSObject 257 | 258 | IBFrameworkSource 259 | UIKit.framework/Headers/UIResponder.h 260 | 261 | 262 | 263 | UIApplication 264 | UIResponder 265 | 266 | IBFrameworkSource 267 | UIKit.framework/Headers/UIApplication.h 268 | 269 | 270 | 271 | UIResponder 272 | NSObject 273 | 274 | 275 | 276 | UIView 277 | 278 | IBFrameworkSource 279 | UIKit.framework/Headers/UITextField.h 280 | 281 | 282 | 283 | UIView 284 | UIResponder 285 | 286 | IBFrameworkSource 287 | UIKit.framework/Headers/UIView.h 288 | 289 | 290 | 291 | UIWindow 292 | UIView 293 | 294 | IBFrameworkSource 295 | UIKit.framework/Headers/UIWindow.h 296 | 297 | 298 | 299 | 300 | 0 301 | IBIPadFramework 302 | 303 | com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS 304 | 305 | 306 | 307 | com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 308 | 309 | 310 | YES 311 | ../OlympicRings.xcodeproj 312 | 3 313 | 105 314 | 315 | 316 | -------------------------------------------------------------------------------- /OlympicRings/iPhone/AppDelegate_iPhone.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate_iPhone.h 3 | // OlympicRings 4 | // 5 | // Created by Dave DeLong on 10/14/10. 6 | // Copyright 2010 Home. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate_iPhone : NSObject { 12 | UIWindow *window; 13 | } 14 | 15 | @property (nonatomic, retain) IBOutlet UIWindow *window; 16 | 17 | @end 18 | 19 | -------------------------------------------------------------------------------- /OlympicRings/iPhone/AppDelegate_iPhone.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate_iPhone.m 3 | // OlympicRings 4 | // 5 | // Created by Dave DeLong on 10/14/10. 6 | // Copyright 2010 Home. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate_iPhone.h" 10 | 11 | @implementation AppDelegate_iPhone 12 | 13 | @synthesize window; 14 | 15 | 16 | #pragma mark - 17 | #pragma mark Application lifecycle 18 | 19 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 20 | 21 | // Override point for customization after application launch. 22 | 23 | [self.window makeKeyAndVisible]; 24 | 25 | return YES; 26 | } 27 | 28 | 29 | - (void)applicationWillResignActive:(UIApplication *)application { 30 | /* 31 | Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 32 | Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 33 | */ 34 | } 35 | 36 | 37 | - (void)applicationDidEnterBackground:(UIApplication *)application { 38 | /* 39 | Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 40 | If your application supports background execution, called instead of applicationWillTerminate: when the user quits. 41 | */ 42 | } 43 | 44 | 45 | - (void)applicationWillEnterForeground:(UIApplication *)application { 46 | /* 47 | Called as part of transition from the background to the inactive state: here you can undo many of the changes made on entering the background. 48 | */ 49 | } 50 | 51 | 52 | - (void)applicationDidBecomeActive:(UIApplication *)application { 53 | /* 54 | Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 55 | */ 56 | } 57 | 58 | 59 | - (void)applicationWillTerminate:(UIApplication *)application { 60 | /* 61 | Called when the application is about to terminate. 62 | See also applicationDidEnterBackground:. 63 | */ 64 | } 65 | 66 | 67 | #pragma mark - 68 | #pragma mark Memory management 69 | 70 | - (void)applicationDidReceiveMemoryWarning:(UIApplication *)application { 71 | /* 72 | Free up as much memory as possible by purging cached data objects that can be recreated (or reloaded from disk) later. 73 | */ 74 | } 75 | 76 | 77 | - (void)dealloc { 78 | [window release]; 79 | [super dealloc]; 80 | } 81 | 82 | 83 | @end 84 | -------------------------------------------------------------------------------- /OlympicRings/iPhone/MainWindow_iPhone.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1024 5 | 10D573 6 | 782 7 | 1038.29 8 | 460.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 105 12 | 13 | 14 | YES 15 | 16 | 17 | 18 | YES 19 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 20 | 21 | 22 | YES 23 | 24 | YES 25 | 26 | 27 | YES 28 | 29 | 30 | 31 | YES 32 | 33 | IBFilesOwner 34 | IBCocoaTouchFramework 35 | 36 | 37 | IBFirstResponder 38 | IBCocoaTouchFramework 39 | 40 | 41 | IBCocoaTouchFramework 42 | 43 | 44 | 45 | 1316 46 | 47 | {320, 480} 48 | 49 | 50 | 1 51 | MSAxIDEAA 52 | 53 | NO 54 | NO 55 | 56 | IBCocoaTouchFramework 57 | YES 58 | 59 | 60 | 61 | 62 | YES 63 | 64 | 65 | delegate 66 | 67 | 68 | 69 | 5 70 | 71 | 72 | 73 | window 74 | 75 | 76 | 77 | 6 78 | 79 | 80 | 81 | 82 | YES 83 | 84 | 0 85 | 86 | 87 | 88 | 89 | 90 | 2 91 | 92 | 93 | YES 94 | 95 | 96 | 97 | 98 | -1 99 | 100 | 101 | File's Owner 102 | 103 | 104 | 4 105 | 106 | 107 | App Delegate 108 | 109 | 110 | -2 111 | 112 | 113 | 114 | 115 | 116 | 117 | YES 118 | 119 | YES 120 | -1.CustomClassName 121 | -2.CustomClassName 122 | 2.IBAttributePlaceholdersKey 123 | 2.IBEditorWindowLastContentRect 124 | 2.IBPluginDependency 125 | 2.UIWindow.visibleAtLaunch 126 | 4.CustomClassName 127 | 4.IBPluginDependency 128 | 129 | 130 | YES 131 | UIApplication 132 | UIResponder 133 | 134 | YES 135 | 136 | 137 | YES 138 | 139 | 140 | {{520, 376}, {320, 480}} 141 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 142 | 143 | AppDelegate_iPhone 144 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 145 | 146 | 147 | 148 | YES 149 | 150 | 151 | YES 152 | 153 | 154 | 155 | 156 | YES 157 | 158 | 159 | YES 160 | 161 | 162 | 163 | 8 164 | 165 | 166 | 167 | YES 168 | 169 | AppDelegate_iPhone 170 | NSObject 171 | 172 | window 173 | UIWindow 174 | 175 | 176 | IBProjectSource 177 | iPhone/AppDelegate_iPhone.h 178 | 179 | 180 | 181 | 182 | YES 183 | 184 | NSObject 185 | 186 | IBFrameworkSource 187 | Foundation.framework/Headers/NSError.h 188 | 189 | 190 | 191 | NSObject 192 | 193 | IBFrameworkSource 194 | Foundation.framework/Headers/NSFileManager.h 195 | 196 | 197 | 198 | NSObject 199 | 200 | IBFrameworkSource 201 | Foundation.framework/Headers/NSKeyValueCoding.h 202 | 203 | 204 | 205 | NSObject 206 | 207 | IBFrameworkSource 208 | Foundation.framework/Headers/NSKeyValueObserving.h 209 | 210 | 211 | 212 | NSObject 213 | 214 | IBFrameworkSource 215 | Foundation.framework/Headers/NSKeyedArchiver.h 216 | 217 | 218 | 219 | NSObject 220 | 221 | IBFrameworkSource 222 | Foundation.framework/Headers/NSObject.h 223 | 224 | 225 | 226 | NSObject 227 | 228 | IBFrameworkSource 229 | Foundation.framework/Headers/NSRunLoop.h 230 | 231 | 232 | 233 | NSObject 234 | 235 | IBFrameworkSource 236 | Foundation.framework/Headers/NSThread.h 237 | 238 | 239 | 240 | NSObject 241 | 242 | IBFrameworkSource 243 | Foundation.framework/Headers/NSURL.h 244 | 245 | 246 | 247 | NSObject 248 | 249 | IBFrameworkSource 250 | Foundation.framework/Headers/NSURLConnection.h 251 | 252 | 253 | 254 | NSObject 255 | 256 | IBFrameworkSource 257 | UIKit.framework/Headers/UIAccessibility.h 258 | 259 | 260 | 261 | NSObject 262 | 263 | IBFrameworkSource 264 | UIKit.framework/Headers/UINibLoading.h 265 | 266 | 267 | 268 | NSObject 269 | 270 | IBFrameworkSource 271 | UIKit.framework/Headers/UIResponder.h 272 | 273 | 274 | 275 | UIApplication 276 | UIResponder 277 | 278 | IBFrameworkSource 279 | UIKit.framework/Headers/UIApplication.h 280 | 281 | 282 | 283 | UIResponder 284 | NSObject 285 | 286 | 287 | 288 | UIView 289 | 290 | IBFrameworkSource 291 | UIKit.framework/Headers/UITextField.h 292 | 293 | 294 | 295 | UIView 296 | UIResponder 297 | 298 | IBFrameworkSource 299 | UIKit.framework/Headers/UIView.h 300 | 301 | 302 | 303 | UIWindow 304 | UIView 305 | 306 | IBFrameworkSource 307 | UIKit.framework/Headers/UIWindow.h 308 | 309 | 310 | 311 | 312 | 0 313 | IBCocoaTouchFramework 314 | 315 | com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS 316 | 317 | 318 | 319 | com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 320 | 321 | 322 | YES 323 | ../OlympicRings.xcodeproj 324 | 3 325 | 105 326 | 327 | 328 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | # Demos 2 | 3 | Some demos showing various concepts relating to Objective-C and Cocoa. 4 | 5 | ## AutozeroingArray 6 | 7 | Contains: 8 | 9 | 1. An `NSMutableArray` subclass (`DDAutozeroingArray`) that maintains auto-zeroing weak references to its items. 10 | 2. An `NSMutableArray` category that allows you to create a "pure" `NSMutableArray` that maintains auto-zeroing weak references to its items. This is slightly less efficient than a `DDAutozeroingArray`. 11 | 12 | Both should work on both iOS and Mac OS X, regardless of GC mode. 13 | 14 | ## DDURLBuilder 15 | 16 | `DDURLBuilder` is essentially a mutable `NSURL`. You can use it to customize the host, path, query, fragment, username, password, etc of an `NSURL`. 17 | 18 | ## DynamicStorage 19 | 20 | Contains `DDDynamicStorageObject`, an `NSObject` subclass that dynamically generates getters and setters for properties declared as `@dynamic`, and uses an `NSMutableDictionary` as the backing store. 21 | 22 | ## FaultingArray 23 | 24 | An `NSArray` subclass that only loads the objects in the array when something else needs them. 25 | 26 | ## GrandSuper 27 | 28 | A project showing how to invoke "grandsuper" (super's super). Uses a private method on `NSInvocation`, so you probably shouldn't use this in a production setting. 29 | 30 | ## JoinPoints 31 | 32 | A **really really really** dangerous project that shows how to inject code before, after, and during any method call. 33 | 34 | THIS IS A PROOF-OF-CONCEPT ONLY, and should **NOT** be used in any sort of production setting. 35 | 36 | ## Olympic Rings 37 | 38 | A simple project showing simple drawing with CoreGraphics and a simple auto-reversing animation. 39 | 40 | ## Screenshot Detector 41 | 42 | A simple project showing how to monitor for screenshots using a persistent `NSMetadataQuery`. -------------------------------------------------------------------------------- /ScreenShot Detector/README.markdown: -------------------------------------------------------------------------------- 1 | # Screenshot Detector 2 | 3 | A simple app that shows how to discover screenshots by leaving a persistent `NSMetadataQuery` running. It can be used to find all existing screenshots, or when a user takes a new screenshot. It relies on a certain spotlight attribute (`kMDItemIsScreenCapture`) that gets set on screenshot files. 4 | 5 | It also uses bindings. Profusely. 6 | 7 | # Screenshot 8 | 9 | This is a screenshot of the screenshot detector, which is showing a screenshot of the screenshot detector showing a screenshot, which is showing a screenshot of the screenshot detector showing a screenshot, which is showing a screenshot of the screenshot detector showing a screenshot, which is showing a screenshot of the screenshot detector showing a screenshot. The universe will implode now. 10 | 11 | ![Screenshot of a screenshot screenshot screenshot screenshot screenshot](https://github.com/davedelong/Demos/raw/master/ScreenShot%20Detector/screenshot.png) -------------------------------------------------------------------------------- /ScreenShot Detector/ScreenShot Detector.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 555149DF1358B82E0099156D /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 555149DE1358B82E0099156D /* Cocoa.framework */; }; 11 | 555149E91358B82E0099156D /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 555149E71358B82E0099156D /* InfoPlist.strings */; }; 12 | 555149EC1358B82E0099156D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 555149EB1358B82E0099156D /* main.m */; }; 13 | 555149EF1358B82E0099156D /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 555149ED1358B82E0099156D /* Credits.rtf */; }; 14 | 555149F21358B82E0099156D /* ScreenShot_DetectorAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 555149F11358B82E0099156D /* ScreenShot_DetectorAppDelegate.m */; }; 15 | 555149F51358B82E0099156D /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 555149F31358B82E0099156D /* MainMenu.xib */; }; 16 | 55514A03135959F90099156D /* ValueTransformers.m in Sources */ = {isa = PBXBuildFile; fileRef = 55514A02135959F90099156D /* ValueTransformers.m */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXFileReference section */ 20 | 555149DA1358B82E0099156D /* ScreenShot Detector.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ScreenShot Detector.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 21 | 555149DE1358B82E0099156D /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 22 | 555149E11358B82E0099156D /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 23 | 555149E21358B82E0099156D /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 24 | 555149E31358B82E0099156D /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 25 | 555149E61358B82E0099156D /* ScreenShot_Detector-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "ScreenShot_Detector-Info.plist"; sourceTree = ""; }; 26 | 555149E81358B82E0099156D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 27 | 555149EA1358B82E0099156D /* ScreenShot_Detector-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ScreenShot_Detector-Prefix.pch"; sourceTree = ""; }; 28 | 555149EB1358B82E0099156D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 29 | 555149EE1358B82E0099156D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; 30 | 555149F01358B82E0099156D /* ScreenShot_DetectorAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ScreenShot_DetectorAppDelegate.h; sourceTree = ""; }; 31 | 555149F11358B82E0099156D /* ScreenShot_DetectorAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ScreenShot_DetectorAppDelegate.m; sourceTree = ""; }; 32 | 555149F41358B82E0099156D /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; }; 33 | 55514A01135959F90099156D /* ValueTransformers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ValueTransformers.h; sourceTree = ""; }; 34 | 55514A02135959F90099156D /* ValueTransformers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ValueTransformers.m; sourceTree = ""; }; 35 | /* End PBXFileReference section */ 36 | 37 | /* Begin PBXFrameworksBuildPhase section */ 38 | 555149D71358B82E0099156D /* Frameworks */ = { 39 | isa = PBXFrameworksBuildPhase; 40 | buildActionMask = 2147483647; 41 | files = ( 42 | 555149DF1358B82E0099156D /* Cocoa.framework in Frameworks */, 43 | ); 44 | runOnlyForDeploymentPostprocessing = 0; 45 | }; 46 | /* End PBXFrameworksBuildPhase section */ 47 | 48 | /* Begin PBXGroup section */ 49 | 555149CF1358B82E0099156D = { 50 | isa = PBXGroup; 51 | children = ( 52 | 555149E41358B82E0099156D /* ScreenShot Detector */, 53 | 555149DD1358B82E0099156D /* Frameworks */, 54 | 555149DB1358B82E0099156D /* Products */, 55 | ); 56 | sourceTree = ""; 57 | }; 58 | 555149DB1358B82E0099156D /* Products */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | 555149DA1358B82E0099156D /* ScreenShot Detector.app */, 62 | ); 63 | name = Products; 64 | sourceTree = ""; 65 | }; 66 | 555149DD1358B82E0099156D /* Frameworks */ = { 67 | isa = PBXGroup; 68 | children = ( 69 | 555149DE1358B82E0099156D /* Cocoa.framework */, 70 | 555149E01358B82E0099156D /* Other Frameworks */, 71 | ); 72 | name = Frameworks; 73 | sourceTree = ""; 74 | }; 75 | 555149E01358B82E0099156D /* Other Frameworks */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | 555149E11358B82E0099156D /* AppKit.framework */, 79 | 555149E21358B82E0099156D /* CoreData.framework */, 80 | 555149E31358B82E0099156D /* Foundation.framework */, 81 | ); 82 | name = "Other Frameworks"; 83 | sourceTree = ""; 84 | }; 85 | 555149E41358B82E0099156D /* ScreenShot Detector */ = { 86 | isa = PBXGroup; 87 | children = ( 88 | 555149F01358B82E0099156D /* ScreenShot_DetectorAppDelegate.h */, 89 | 555149F11358B82E0099156D /* ScreenShot_DetectorAppDelegate.m */, 90 | 555149F31358B82E0099156D /* MainMenu.xib */, 91 | 55514A01135959F90099156D /* ValueTransformers.h */, 92 | 55514A02135959F90099156D /* ValueTransformers.m */, 93 | 555149E51358B82E0099156D /* Supporting Files */, 94 | ); 95 | path = "ScreenShot Detector"; 96 | sourceTree = ""; 97 | }; 98 | 555149E51358B82E0099156D /* Supporting Files */ = { 99 | isa = PBXGroup; 100 | children = ( 101 | 555149E61358B82E0099156D /* ScreenShot_Detector-Info.plist */, 102 | 555149E71358B82E0099156D /* InfoPlist.strings */, 103 | 555149EA1358B82E0099156D /* ScreenShot_Detector-Prefix.pch */, 104 | 555149EB1358B82E0099156D /* main.m */, 105 | 555149ED1358B82E0099156D /* Credits.rtf */, 106 | ); 107 | name = "Supporting Files"; 108 | sourceTree = ""; 109 | }; 110 | /* End PBXGroup section */ 111 | 112 | /* Begin PBXNativeTarget section */ 113 | 555149D91358B82E0099156D /* ScreenShot Detector */ = { 114 | isa = PBXNativeTarget; 115 | buildConfigurationList = 555149F81358B82E0099156D /* Build configuration list for PBXNativeTarget "ScreenShot Detector" */; 116 | buildPhases = ( 117 | 555149D61358B82E0099156D /* Sources */, 118 | 555149D71358B82E0099156D /* Frameworks */, 119 | 555149D81358B82E0099156D /* Resources */, 120 | ); 121 | buildRules = ( 122 | ); 123 | dependencies = ( 124 | ); 125 | name = "ScreenShot Detector"; 126 | productName = "ScreenShot Detector"; 127 | productReference = 555149DA1358B82E0099156D /* ScreenShot Detector.app */; 128 | productType = "com.apple.product-type.application"; 129 | }; 130 | /* End PBXNativeTarget section */ 131 | 132 | /* Begin PBXProject section */ 133 | 555149D11358B82E0099156D /* Project object */ = { 134 | isa = PBXProject; 135 | buildConfigurationList = 555149D41358B82E0099156D /* Build configuration list for PBXProject "ScreenShot Detector" */; 136 | compatibilityVersion = "Xcode 3.2"; 137 | developmentRegion = English; 138 | hasScannedForEncodings = 0; 139 | knownRegions = ( 140 | en, 141 | ); 142 | mainGroup = 555149CF1358B82E0099156D; 143 | productRefGroup = 555149DB1358B82E0099156D /* Products */; 144 | projectDirPath = ""; 145 | projectRoot = ""; 146 | targets = ( 147 | 555149D91358B82E0099156D /* ScreenShot Detector */, 148 | ); 149 | }; 150 | /* End PBXProject section */ 151 | 152 | /* Begin PBXResourcesBuildPhase section */ 153 | 555149D81358B82E0099156D /* Resources */ = { 154 | isa = PBXResourcesBuildPhase; 155 | buildActionMask = 2147483647; 156 | files = ( 157 | 555149E91358B82E0099156D /* InfoPlist.strings in Resources */, 158 | 555149EF1358B82E0099156D /* Credits.rtf in Resources */, 159 | 555149F51358B82E0099156D /* MainMenu.xib in Resources */, 160 | ); 161 | runOnlyForDeploymentPostprocessing = 0; 162 | }; 163 | /* End PBXResourcesBuildPhase section */ 164 | 165 | /* Begin PBXSourcesBuildPhase section */ 166 | 555149D61358B82E0099156D /* Sources */ = { 167 | isa = PBXSourcesBuildPhase; 168 | buildActionMask = 2147483647; 169 | files = ( 170 | 555149EC1358B82E0099156D /* main.m in Sources */, 171 | 555149F21358B82E0099156D /* ScreenShot_DetectorAppDelegate.m in Sources */, 172 | 55514A03135959F90099156D /* ValueTransformers.m in Sources */, 173 | ); 174 | runOnlyForDeploymentPostprocessing = 0; 175 | }; 176 | /* End PBXSourcesBuildPhase section */ 177 | 178 | /* Begin PBXVariantGroup section */ 179 | 555149E71358B82E0099156D /* InfoPlist.strings */ = { 180 | isa = PBXVariantGroup; 181 | children = ( 182 | 555149E81358B82E0099156D /* en */, 183 | ); 184 | name = InfoPlist.strings; 185 | sourceTree = ""; 186 | }; 187 | 555149ED1358B82E0099156D /* Credits.rtf */ = { 188 | isa = PBXVariantGroup; 189 | children = ( 190 | 555149EE1358B82E0099156D /* en */, 191 | ); 192 | name = Credits.rtf; 193 | sourceTree = ""; 194 | }; 195 | 555149F31358B82E0099156D /* MainMenu.xib */ = { 196 | isa = PBXVariantGroup; 197 | children = ( 198 | 555149F41358B82E0099156D /* en */, 199 | ); 200 | name = MainMenu.xib; 201 | sourceTree = ""; 202 | }; 203 | /* End PBXVariantGroup section */ 204 | 205 | /* Begin XCBuildConfiguration section */ 206 | 555149F61358B82E0099156D /* Debug */ = { 207 | isa = XCBuildConfiguration; 208 | buildSettings = { 209 | ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; 210 | GCC_C_LANGUAGE_STANDARD = gnu99; 211 | GCC_OPTIMIZATION_LEVEL = 0; 212 | GCC_PREPROCESSOR_DEFINITIONS = DEBUG; 213 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 214 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 215 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 216 | GCC_WARN_UNUSED_VARIABLE = YES; 217 | MACOSX_DEPLOYMENT_TARGET = 10.6; 218 | ONLY_ACTIVE_ARCH = YES; 219 | SDKROOT = macosx; 220 | }; 221 | name = Debug; 222 | }; 223 | 555149F71358B82E0099156D /* Release */ = { 224 | isa = XCBuildConfiguration; 225 | buildSettings = { 226 | ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; 227 | GCC_C_LANGUAGE_STANDARD = gnu99; 228 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 229 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 230 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 231 | GCC_WARN_UNUSED_VARIABLE = YES; 232 | MACOSX_DEPLOYMENT_TARGET = 10.6; 233 | SDKROOT = macosx; 234 | }; 235 | name = Release; 236 | }; 237 | 555149F91358B82E0099156D /* Debug */ = { 238 | isa = XCBuildConfiguration; 239 | buildSettings = { 240 | ALWAYS_SEARCH_USER_PATHS = NO; 241 | COPY_PHASE_STRIP = NO; 242 | GCC_DYNAMIC_NO_PIC = NO; 243 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 244 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 245 | GCC_PREFIX_HEADER = "ScreenShot Detector/ScreenShot_Detector-Prefix.pch"; 246 | INFOPLIST_FILE = "ScreenShot Detector/ScreenShot_Detector-Info.plist"; 247 | PRODUCT_NAME = "$(TARGET_NAME)"; 248 | WRAPPER_EXTENSION = app; 249 | }; 250 | name = Debug; 251 | }; 252 | 555149FA1358B82E0099156D /* Release */ = { 253 | isa = XCBuildConfiguration; 254 | buildSettings = { 255 | ALWAYS_SEARCH_USER_PATHS = NO; 256 | COPY_PHASE_STRIP = YES; 257 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 258 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 259 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 260 | GCC_PREFIX_HEADER = "ScreenShot Detector/ScreenShot_Detector-Prefix.pch"; 261 | INFOPLIST_FILE = "ScreenShot Detector/ScreenShot_Detector-Info.plist"; 262 | PRODUCT_NAME = "$(TARGET_NAME)"; 263 | WRAPPER_EXTENSION = app; 264 | }; 265 | name = Release; 266 | }; 267 | /* End XCBuildConfiguration section */ 268 | 269 | /* Begin XCConfigurationList section */ 270 | 555149D41358B82E0099156D /* Build configuration list for PBXProject "ScreenShot Detector" */ = { 271 | isa = XCConfigurationList; 272 | buildConfigurations = ( 273 | 555149F61358B82E0099156D /* Debug */, 274 | 555149F71358B82E0099156D /* Release */, 275 | ); 276 | defaultConfigurationIsVisible = 0; 277 | defaultConfigurationName = Release; 278 | }; 279 | 555149F81358B82E0099156D /* Build configuration list for PBXNativeTarget "ScreenShot Detector" */ = { 280 | isa = XCConfigurationList; 281 | buildConfigurations = ( 282 | 555149F91358B82E0099156D /* Debug */, 283 | 555149FA1358B82E0099156D /* Release */, 284 | ); 285 | defaultConfigurationIsVisible = 0; 286 | }; 287 | /* End XCConfigurationList section */ 288 | }; 289 | rootObject = 555149D11358B82E0099156D /* Project object */; 290 | } 291 | -------------------------------------------------------------------------------- /ScreenShot Detector/ScreenShot Detector/ScreenShot_Detector-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.davedelong.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | ${MACOSX_DEPLOYMENT_TARGET} 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /ScreenShot Detector/ScreenShot Detector/ScreenShot_Detector-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'ScreenShot Detector' target in the 'ScreenShot Detector' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /ScreenShot Detector/ScreenShot Detector/ScreenShot_DetectorAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // ScreenShot_DetectorAppDelegate.h 3 | // ScreenShot Detector 4 | // 5 | // Created by Dave DeLong on 4/15/11. 6 | // Copyright 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ScreenShot_DetectorAppDelegate : NSObject { 12 | @private 13 | NSWindow *window; 14 | NSMetadataQuery *query; 15 | } 16 | 17 | @property (assign) IBOutlet NSWindow *window; 18 | @property (nonatomic, copy) NSArray *queryResults; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /ScreenShot Detector/ScreenShot Detector/ScreenShot_DetectorAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // ScreenShot_DetectorAppDelegate.m 3 | // ScreenShot Detector 4 | // 5 | // Created by Dave DeLong on 4/15/11. 6 | // Copyright 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "ScreenShot_DetectorAppDelegate.h" 10 | 11 | @implementation ScreenShot_DetectorAppDelegate 12 | 13 | @synthesize window; 14 | @synthesize queryResults; 15 | 16 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 17 | { 18 | // Insert code here to initialize your application 19 | query = [[NSMetadataQuery alloc] init]; 20 | 21 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(queryUpdated:) name:NSMetadataQueryDidStartGatheringNotification object:query]; 22 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(queryUpdated:) name:NSMetadataQueryDidUpdateNotification object:query]; 23 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(queryUpdated:) name:NSMetadataQueryDidFinishGatheringNotification object:query]; 24 | 25 | [query setDelegate:self]; 26 | [query setPredicate:[NSPredicate predicateWithFormat:@"kMDItemIsScreenCapture = 1"]]; 27 | [query startQuery]; 28 | } 29 | 30 | - (void)applicationWillTerminate:(NSNotification *)notification { 31 | [query stopQuery]; 32 | [query setDelegate:nil]; 33 | [query release], query = nil; 34 | 35 | [self setQueryResults:nil]; 36 | } 37 | 38 | - (void)queryUpdated:(NSNotification *)note { 39 | [self setQueryResults:[query results]]; 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /ScreenShot Detector/ScreenShot Detector/ValueTransformers.h: -------------------------------------------------------------------------------- 1 | // 2 | // ValueTransformers.h 3 | // ScreenShot Detector 4 | // 5 | // Created by Dave DeLong on 4/15/11. 6 | // Copyright 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface ImagePathValueTransformer : NSValueTransformer @end 13 | @interface NSURLBoxerValueTransformer : NSValueTransformer @end 14 | -------------------------------------------------------------------------------- /ScreenShot Detector/ScreenShot Detector/ValueTransformers.m: -------------------------------------------------------------------------------- 1 | // 2 | // ValueTransformers.m 3 | // ScreenShot Detector 4 | // 5 | // Created by Dave DeLong on 4/15/11. 6 | // Copyright 2011 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "ValueTransformers.h" 10 | 11 | 12 | @implementation ImagePathValueTransformer 13 | 14 | + (Class)transformedValueClass { return [NSImage class]; } 15 | + (BOOL)allowsReverseTransformation { return NO; } 16 | 17 | - (id)transformedValue:(id)value { 18 | return [[[NSImage alloc] initWithContentsOfFile:value] autorelease]; 19 | } 20 | 21 | @end 22 | 23 | 24 | @implementation NSURLBoxerValueTransformer 25 | 26 | + (Class)transformedValueClass { return [NSURL class]; } 27 | + (BOOL)allowsReverseTransformation { return NO; } 28 | 29 | - (id)transformedValue:(id)value { 30 | if (value == nil) { return nil; } 31 | return [NSURL fileURLWithPath:value]; 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /ScreenShot Detector/ScreenShot Detector/en.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} 2 | {\colortbl;\red255\green255\blue255;} 3 | \paperw9840\paperh8400 4 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural 5 | 6 | \f0\b\fs24 \cf0 Engineering: 7 | \b0 \ 8 | Some people\ 9 | \ 10 | 11 | \b Human Interface Design: 12 | \b0 \ 13 | Some other people\ 14 | \ 15 | 16 | \b Testing: 17 | \b0 \ 18 | Hopefully not nobody\ 19 | \ 20 | 21 | \b Documentation: 22 | \b0 \ 23 | Whoever\ 24 | \ 25 | 26 | \b With special thanks to: 27 | \b0 \ 28 | Mom\ 29 | } 30 | -------------------------------------------------------------------------------- /ScreenShot Detector/ScreenShot Detector/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /ScreenShot Detector/ScreenShot Detector/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ScreenShot Detector 4 | // 5 | // Created by Dave DeLong on 4/15/11. 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 | -------------------------------------------------------------------------------- /ScreenShot Detector/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davedelong/Demos/3d928e1293506342e91e0be1dcf88064956878ed/ScreenShot Detector/screenshot.png --------------------------------------------------------------------------------