├── PZIndexedArray ├── ___PZIndexedArray___h___0x39al ├── ___PZIndexedArray___m___JwCywy ├── PZIndexedArray-Prefix.pch ├── PZIndexedArray.h └── PZIndexedArray.m ├── .DS_Store ├── README └── PZIndexedArray.xcodeproj ├── project.xcworkspace ├── contents.xcworkspacedata └── xcuserdata │ └── pzearfoss.xcuserdatad │ └── UserInterfaceState.xcuserstate ├── xcuserdata └── pzearfoss.xcuserdatad │ └── xcschemes │ ├── xcschememanagement.plist │ └── PZIndexedArray.xcscheme └── project.pbxproj /PZIndexedArray/___PZIndexedArray___h___0x39al: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /PZIndexedArray/___PZIndexedArray___m___JwCywy: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patzearfoss/IndexArray/HEAD/.DS_Store -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | PZIndexedArray is a simple data structure that closely aligns with a UITableViews sections and rows. -------------------------------------------------------------------------------- /PZIndexedArray/PZIndexedArray-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'PZIndexedArray' target in the 'PZIndexedArray' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /PZIndexedArray.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /PZIndexedArray.xcodeproj/project.xcworkspace/xcuserdata/pzearfoss.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/patzearfoss/IndexArray/HEAD/PZIndexedArray.xcodeproj/project.xcworkspace/xcuserdata/pzearfoss.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /PZIndexedArray.xcodeproj/xcuserdata/pzearfoss.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | PZIndexedArray.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 2638EC6E145C7D1D0008A22B 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /PZIndexedArray.xcodeproj/xcuserdata/pzearfoss.xcuserdatad/xcschemes/PZIndexedArray.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 14 | 20 | 21 | 22 | 23 | 24 | 29 | 30 | 31 | 32 | 40 | 41 | 42 | 43 | 49 | 50 | 52 | 53 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /PZIndexedArray/PZIndexedArray.h: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2011 Pat Zearfoss, http://zearfoss.wordpress.com 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining 4 | //a copy of this software and associated documentation files (the "Software"), 5 | //to deal in the Software without restriction, including 6 | //without limitation the rights to use, copy, modify, merge, publish, 7 | //distribute, sublicense, and/or sell copies of the Software, and to 8 | //permit persons to whom the Software is furnished to do so, subject to 9 | //the following conditions: 10 | // 11 | //The above copyright notice and this permission notice shall be 12 | //included in all copies or substantial portions of the Software. 13 | // 14 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | //EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | //MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | //NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | //LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | //OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | //WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | #import 23 | 24 | @interface PZIndexedArray : NSObject 25 | { 26 | @private 27 | NSMutableDictionary *dictionary_; 28 | NSMutableOrderedSet *orderedKeys_; 29 | 30 | SEL keySortSelector_; 31 | SEL objectSortSelector_; 32 | NSComparator keySortComparator_; 33 | NSComparator objectSortComparator_; 34 | 35 | BOOL sortsKeys_; 36 | BOOL sortsObjects_; 37 | BOOL usesComparatorForKeys_; 38 | BOOL usesComparatorForObjects_; 39 | } 40 | 41 | @property (nonatomic, assign) SEL keySortSelector; 42 | @property (nonatomic, assign) SEL objectSortSelector; 43 | @property (nonatomic, copy) NSComparator keySortComparator; 44 | @property (nonatomic, copy) NSComparator objectSortComparator; 45 | 46 | // accessing keys 47 | - (id)keyAtIndex:(NSUInteger)index; 48 | - (NSOrderedSet *)allKeys; 49 | - (NSUInteger)keyCount; 50 | - (BOOL)hasKey:(id)key; 51 | - (NSUInteger)indexForKey:(id)key; 52 | 53 | // accessing objects 54 | - (id)objectForKeyAtIndex:(NSUInteger)keyIndex objectIndex:(NSUInteger)objIndex; 55 | - (id)objectForKey:(id)key index:(NSUInteger)index; 56 | - (NSArray *)allObjectsForKey:(id)key; 57 | - (NSUInteger)count; 58 | 59 | // adding objects 60 | - (void)addObject:(id)object forKey:(id)key; 61 | 62 | // removing objects 63 | - (void)removeObject:(id)object forKey:(id)key; 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /PZIndexedArray.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2638EC73145C7D1D0008A22B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2638EC72145C7D1D0008A22B /* Foundation.framework */; }; 11 | 2638EC81145C7D330008A22B /* PZIndexedArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 2638EC7F145C7D330008A22B /* PZIndexedArray.h */; }; 12 | 2638EC82145C7D330008A22B /* PZIndexedArray.m in Sources */ = {isa = PBXBuildFile; fileRef = 2638EC80145C7D330008A22B /* PZIndexedArray.m */; }; 13 | /* End PBXBuildFile section */ 14 | 15 | /* Begin PBXFileReference section */ 16 | 2638EC6F145C7D1D0008A22B /* libPZIndexedArray.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPZIndexedArray.a; sourceTree = BUILT_PRODUCTS_DIR; }; 17 | 2638EC72145C7D1D0008A22B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 18 | 2638EC76145C7D1D0008A22B /* PZIndexedArray-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "PZIndexedArray-Prefix.pch"; sourceTree = ""; }; 19 | 2638EC7F145C7D330008A22B /* PZIndexedArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PZIndexedArray.h; sourceTree = ""; }; 20 | 2638EC80145C7D330008A22B /* PZIndexedArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PZIndexedArray.m; sourceTree = ""; }; 21 | /* End PBXFileReference section */ 22 | 23 | /* Begin PBXFrameworksBuildPhase section */ 24 | 2638EC6C145C7D1D0008A22B /* Frameworks */ = { 25 | isa = PBXFrameworksBuildPhase; 26 | buildActionMask = 2147483647; 27 | files = ( 28 | 2638EC73145C7D1D0008A22B /* Foundation.framework in Frameworks */, 29 | ); 30 | runOnlyForDeploymentPostprocessing = 0; 31 | }; 32 | /* End PBXFrameworksBuildPhase section */ 33 | 34 | /* Begin PBXGroup section */ 35 | 2638EC64145C7D1D0008A22B = { 36 | isa = PBXGroup; 37 | children = ( 38 | 2638EC74145C7D1D0008A22B /* PZIndexedArray */, 39 | 2638EC71145C7D1D0008A22B /* Frameworks */, 40 | 2638EC70145C7D1D0008A22B /* Products */, 41 | ); 42 | sourceTree = ""; 43 | }; 44 | 2638EC70145C7D1D0008A22B /* Products */ = { 45 | isa = PBXGroup; 46 | children = ( 47 | 2638EC6F145C7D1D0008A22B /* libPZIndexedArray.a */, 48 | ); 49 | name = Products; 50 | sourceTree = ""; 51 | }; 52 | 2638EC71145C7D1D0008A22B /* Frameworks */ = { 53 | isa = PBXGroup; 54 | children = ( 55 | 2638EC72145C7D1D0008A22B /* Foundation.framework */, 56 | ); 57 | name = Frameworks; 58 | sourceTree = ""; 59 | }; 60 | 2638EC74145C7D1D0008A22B /* PZIndexedArray */ = { 61 | isa = PBXGroup; 62 | children = ( 63 | 2638EC7F145C7D330008A22B /* PZIndexedArray.h */, 64 | 2638EC80145C7D330008A22B /* PZIndexedArray.m */, 65 | 2638EC75145C7D1D0008A22B /* Supporting Files */, 66 | ); 67 | path = PZIndexedArray; 68 | sourceTree = ""; 69 | }; 70 | 2638EC75145C7D1D0008A22B /* Supporting Files */ = { 71 | isa = PBXGroup; 72 | children = ( 73 | 2638EC76145C7D1D0008A22B /* PZIndexedArray-Prefix.pch */, 74 | ); 75 | name = "Supporting Files"; 76 | sourceTree = ""; 77 | }; 78 | /* End PBXGroup section */ 79 | 80 | /* Begin PBXHeadersBuildPhase section */ 81 | 2638EC6D145C7D1D0008A22B /* Headers */ = { 82 | isa = PBXHeadersBuildPhase; 83 | buildActionMask = 2147483647; 84 | files = ( 85 | 2638EC81145C7D330008A22B /* PZIndexedArray.h in Headers */, 86 | ); 87 | runOnlyForDeploymentPostprocessing = 0; 88 | }; 89 | /* End PBXHeadersBuildPhase section */ 90 | 91 | /* Begin PBXNativeTarget section */ 92 | 2638EC6E145C7D1D0008A22B /* PZIndexedArray */ = { 93 | isa = PBXNativeTarget; 94 | buildConfigurationList = 2638EC7C145C7D1D0008A22B /* Build configuration list for PBXNativeTarget "PZIndexedArray" */; 95 | buildPhases = ( 96 | 2638EC6B145C7D1D0008A22B /* Sources */, 97 | 2638EC6C145C7D1D0008A22B /* Frameworks */, 98 | 2638EC6D145C7D1D0008A22B /* Headers */, 99 | ); 100 | buildRules = ( 101 | ); 102 | dependencies = ( 103 | ); 104 | name = PZIndexedArray; 105 | productName = PZIndexedArray; 106 | productReference = 2638EC6F145C7D1D0008A22B /* libPZIndexedArray.a */; 107 | productType = "com.apple.product-type.library.static"; 108 | }; 109 | /* End PBXNativeTarget section */ 110 | 111 | /* Begin PBXProject section */ 112 | 2638EC66145C7D1D0008A22B /* Project object */ = { 113 | isa = PBXProject; 114 | attributes = { 115 | LastUpgradeCheck = 0420; 116 | ORGANIZATIONNAME = "Mindgrub Technologies"; 117 | }; 118 | buildConfigurationList = 2638EC69145C7D1D0008A22B /* Build configuration list for PBXProject "PZIndexedArray" */; 119 | compatibilityVersion = "Xcode 3.2"; 120 | developmentRegion = English; 121 | hasScannedForEncodings = 0; 122 | knownRegions = ( 123 | en, 124 | ); 125 | mainGroup = 2638EC64145C7D1D0008A22B; 126 | productRefGroup = 2638EC70145C7D1D0008A22B /* Products */; 127 | projectDirPath = ""; 128 | projectRoot = ""; 129 | targets = ( 130 | 2638EC6E145C7D1D0008A22B /* PZIndexedArray */, 131 | ); 132 | }; 133 | /* End PBXProject section */ 134 | 135 | /* Begin PBXSourcesBuildPhase section */ 136 | 2638EC6B145C7D1D0008A22B /* Sources */ = { 137 | isa = PBXSourcesBuildPhase; 138 | buildActionMask = 2147483647; 139 | files = ( 140 | 2638EC82145C7D330008A22B /* PZIndexedArray.m in Sources */, 141 | ); 142 | runOnlyForDeploymentPostprocessing = 0; 143 | }; 144 | /* End PBXSourcesBuildPhase section */ 145 | 146 | /* Begin XCBuildConfiguration section */ 147 | 2638EC7A145C7D1D0008A22B /* Debug */ = { 148 | isa = XCBuildConfiguration; 149 | buildSettings = { 150 | ALWAYS_SEARCH_USER_PATHS = NO; 151 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 152 | COPY_PHASE_STRIP = NO; 153 | GCC_C_LANGUAGE_STANDARD = gnu99; 154 | GCC_DYNAMIC_NO_PIC = NO; 155 | GCC_OPTIMIZATION_LEVEL = 0; 156 | GCC_PREPROCESSOR_DEFINITIONS = ( 157 | "DEBUG=1", 158 | "$(inherited)", 159 | ); 160 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 161 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 162 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 163 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 164 | GCC_WARN_UNUSED_VARIABLE = YES; 165 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 166 | SDKROOT = iphoneos; 167 | }; 168 | name = Debug; 169 | }; 170 | 2638EC7B145C7D1D0008A22B /* Release */ = { 171 | isa = XCBuildConfiguration; 172 | buildSettings = { 173 | ALWAYS_SEARCH_USER_PATHS = NO; 174 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 175 | COPY_PHASE_STRIP = YES; 176 | GCC_C_LANGUAGE_STANDARD = gnu99; 177 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 178 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 179 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 180 | GCC_WARN_UNUSED_VARIABLE = YES; 181 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 182 | SDKROOT = iphoneos; 183 | VALIDATE_PRODUCT = YES; 184 | }; 185 | name = Release; 186 | }; 187 | 2638EC7D145C7D1D0008A22B /* Debug */ = { 188 | isa = XCBuildConfiguration; 189 | buildSettings = { 190 | DSTROOT = /tmp/PZIndexedArray.dst; 191 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 192 | GCC_PREFIX_HEADER = "PZIndexedArray/PZIndexedArray-Prefix.pch"; 193 | OTHER_LDFLAGS = "-ObjC"; 194 | PRODUCT_NAME = "$(TARGET_NAME)"; 195 | SKIP_INSTALL = YES; 196 | }; 197 | name = Debug; 198 | }; 199 | 2638EC7E145C7D1D0008A22B /* Release */ = { 200 | isa = XCBuildConfiguration; 201 | buildSettings = { 202 | DSTROOT = /tmp/PZIndexedArray.dst; 203 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 204 | GCC_PREFIX_HEADER = "PZIndexedArray/PZIndexedArray-Prefix.pch"; 205 | OTHER_LDFLAGS = "-ObjC"; 206 | PRODUCT_NAME = "$(TARGET_NAME)"; 207 | SKIP_INSTALL = YES; 208 | }; 209 | name = Release; 210 | }; 211 | /* End XCBuildConfiguration section */ 212 | 213 | /* Begin XCConfigurationList section */ 214 | 2638EC69145C7D1D0008A22B /* Build configuration list for PBXProject "PZIndexedArray" */ = { 215 | isa = XCConfigurationList; 216 | buildConfigurations = ( 217 | 2638EC7A145C7D1D0008A22B /* Debug */, 218 | 2638EC7B145C7D1D0008A22B /* Release */, 219 | ); 220 | defaultConfigurationIsVisible = 0; 221 | defaultConfigurationName = Release; 222 | }; 223 | 2638EC7C145C7D1D0008A22B /* Build configuration list for PBXNativeTarget "PZIndexedArray" */ = { 224 | isa = XCConfigurationList; 225 | buildConfigurations = ( 226 | 2638EC7D145C7D1D0008A22B /* Debug */, 227 | 2638EC7E145C7D1D0008A22B /* Release */, 228 | ); 229 | defaultConfigurationIsVisible = 0; 230 | }; 231 | /* End XCConfigurationList section */ 232 | }; 233 | rootObject = 2638EC66145C7D1D0008A22B /* Project object */; 234 | } 235 | -------------------------------------------------------------------------------- /PZIndexedArray/PZIndexedArray.m: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2011 Pat Zearfoss, http://zearfoss.wordpress.com 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining 4 | //a copy of this software and associated documentation files (the "Software"), 5 | //to deal in the Software without restriction, including 6 | //without limitation the rights to use, copy, modify, merge, publish, 7 | //distribute, sublicense, and/or sell copies of the Software, and to 8 | //permit persons to whom the Software is furnished to do so, subject to 9 | //the following conditions: 10 | // 11 | //The above copyright notice and this permission notice shall be 12 | //included in all copies or substantial portions of the Software. 13 | // 14 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | //EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | //MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | //NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | //LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | //OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | //WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | #import "PZIndexedArray.h" 23 | 24 | @interface PZIndexedArray() 25 | - (void)insertKeySorted:(id)key; 26 | - (void)insertObject:(id)object array:(NSMutableArray *)array; 27 | 28 | @end 29 | 30 | @implementation PZIndexedArray 31 | @synthesize keySortSelector = keySortSelector_; 32 | @synthesize objectSortSelector = objectSortSelector_; 33 | @synthesize keySortComparator = keySortComparator_; 34 | @synthesize objectSortComparator = objectSortComparator_; 35 | 36 | - (id)init 37 | { 38 | self = [super init]; 39 | if (self) 40 | { 41 | dictionary_ = [[NSMutableDictionary alloc] init]; 42 | orderedKeys_ = [[NSMutableOrderedSet alloc] init]; 43 | 44 | usesComparatorForObjects_ = YES; 45 | usesComparatorForKeys_ = YES; 46 | } 47 | 48 | return self; 49 | } 50 | 51 | - (void)dealloc 52 | { 53 | [keySortComparator_ release]; 54 | [objectSortComparator_ release]; 55 | [dictionary_ release]; 56 | [orderedKeys_ release]; 57 | [super dealloc]; 58 | } 59 | 60 | #pragma mark NSCopying 61 | - (id)copyWithZone:(NSZone *)zone 62 | { 63 | PZIndexedArray *copy = [[[self class] alloc] init]; 64 | copy->orderedKeys_ = [orderedKeys_ copyWithZone:zone]; 65 | copy->dictionary_ = [dictionary_ copyWithZone:zone]; 66 | copy.keySortComparator = self.keySortComparator; 67 | copy.objectSortComparator = self.objectSortComparator; 68 | copy.keySortSelector = self.keySortSelector; 69 | copy.objectSortSelector = self.objectSortSelector; 70 | 71 | return copy; 72 | } 73 | 74 | // accessing keys 75 | - (id)keyAtIndex:(NSUInteger)index 76 | { 77 | if ([orderedKeys_ count] == 0) 78 | { 79 | return nil; 80 | } 81 | 82 | return [orderedKeys_ objectAtIndex:index]; 83 | } 84 | 85 | - (NSOrderedSet *)allKeys 86 | { 87 | return [orderedKeys_ copy]; 88 | } 89 | 90 | - (NSUInteger)keyCount 91 | { 92 | return [orderedKeys_ count]; 93 | } 94 | 95 | - (BOOL)hasKey:(id)key 96 | { 97 | NSInteger index = [orderedKeys_ indexOfObject:key]; 98 | return index != NSNotFound; 99 | } 100 | 101 | - (NSUInteger)indexForKey:(id)key 102 | { 103 | return [orderedKeys_ indexOfObject:key]; 104 | } 105 | 106 | // accessing objects 107 | - (id)objectForKey:(id)key index:(NSUInteger)index 108 | { 109 | NSArray *array = [dictionary_ objectForKey:key]; 110 | if (array && index < [array count]) 111 | { 112 | return [array objectAtIndex:index]; 113 | } 114 | 115 | return nil; 116 | } 117 | 118 | - (id)objectForKeyAtIndex:(NSUInteger)keyIndex objectIndex:(NSUInteger)objIndex 119 | { 120 | id key = [self keyAtIndex:keyIndex]; 121 | return [self objectForKey:key index:objIndex]; 122 | } 123 | 124 | - (NSArray *)allObjectsForKey:(id)key 125 | { 126 | return [[dictionary_ objectForKey:key] copy]; 127 | } 128 | 129 | - (NSUInteger)count 130 | { 131 | NSUInteger count = 0; 132 | for (id key in [dictionary_ allKeys]) 133 | { 134 | count += [[dictionary_ objectForKey:key] count]; 135 | } 136 | 137 | return count; 138 | } 139 | 140 | // adding objects 141 | - (void)addObject:(id)object forKey:(id)key 142 | { 143 | NSMutableArray *array = [dictionary_ objectForKey:key]; 144 | if (!array) 145 | { 146 | array = [NSMutableArray array]; 147 | [dictionary_ setObject:array forKey:key]; 148 | 149 | if (sortsKeys_) 150 | { 151 | [self insertKeySorted:key]; 152 | } 153 | else 154 | { 155 | [orderedKeys_ addObject:key]; 156 | } 157 | } 158 | 159 | if (sortsObjects_) 160 | { 161 | [self insertObject:object array:array]; 162 | } 163 | else 164 | { 165 | [array addObject:object]; 166 | } 167 | } 168 | 169 | // removing 170 | - (void)removeObject:(id)object forKey:(id)key 171 | { 172 | NSMutableArray *array = [dictionary_ objectForKey:key]; 173 | [array removeObject:object]; 174 | if ([array count] == 0) 175 | { 176 | [orderedKeys_ removeObject:key]; 177 | [dictionary_ removeObjectForKey:key]; 178 | } 179 | } 180 | 181 | #pragma mark - sorting 182 | - (void)insertKeySorted:(id)key 183 | { 184 | if ([orderedKeys_ count] == 0) 185 | { 186 | [orderedKeys_ addObject:key]; 187 | return; 188 | } 189 | 190 | __block NSUInteger insertIndex = -1; 191 | __block NSInvocation *selectorInvocation = nil; 192 | if (!usesComparatorForKeys_) 193 | { 194 | selectorInvocation = [NSInvocation invocationWithMethodSignature:[key methodSignatureForSelector:keySortSelector_]]; 195 | [selectorInvocation setTarget:key]; 196 | [selectorInvocation setSelector:keySortSelector_]; 197 | } 198 | 199 | [orderedKeys_ enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 200 | if (idx < [orderedKeys_ count]) 201 | { 202 | NSComparisonResult result = NSOrderedAscending; 203 | if (usesComparatorForKeys_) 204 | { 205 | result = self.keySortComparator(key, obj); 206 | } 207 | else 208 | { 209 | [selectorInvocation setArgument:&obj atIndex:2]; 210 | [selectorInvocation invoke]; 211 | [selectorInvocation getReturnValue:&result]; 212 | } 213 | 214 | if (result == NSOrderedAscending) 215 | { 216 | insertIndex = idx; 217 | *stop = YES; 218 | } 219 | 220 | } 221 | }]; 222 | 223 | if (insertIndex == -1) 224 | { 225 | [orderedKeys_ addObject:key]; 226 | } 227 | else 228 | { 229 | [orderedKeys_ insertObject:key atIndex:insertIndex]; 230 | } 231 | } 232 | 233 | - (void)insertObject:(id)object array:(NSMutableArray *)array 234 | { 235 | if ([array count] == 0) 236 | { 237 | [array addObject:object]; 238 | return; 239 | } 240 | 241 | __block NSUInteger insertIndex = -1; 242 | __block NSInvocation *selectorInvocation = nil; 243 | if (!usesComparatorForObjects_) 244 | { 245 | selectorInvocation = [NSInvocation invocationWithMethodSignature:[object methodSignatureForSelector:objectSortSelector_]]; 246 | } 247 | 248 | [array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 249 | NSComparisonResult result = NSOrderedAscending; 250 | 251 | if (usesComparatorForObjects_) 252 | { 253 | result = self.objectSortComparator(object, obj); 254 | } 255 | else 256 | { 257 | [selectorInvocation setArgument:&obj atIndex:2]; 258 | [selectorInvocation invoke]; 259 | [selectorInvocation getReturnValue:&result]; 260 | //result = [object performSelector:objectSortSelector_ withObject:obj]; 261 | } 262 | 263 | if (result == NSOrderedAscending) 264 | { 265 | insertIndex = idx; 266 | *stop = YES; 267 | } 268 | }]; 269 | 270 | if (insertIndex == -1) 271 | { 272 | [array addObject:object]; 273 | } 274 | else 275 | { 276 | [array insertObject:object atIndex:insertIndex]; 277 | } 278 | } 279 | 280 | #pragma mark - handling selectors and comparators 281 | - (void)setKeySortSelector:(SEL)keySortSelector 282 | { 283 | if (keySortSelector != keySortSelector_) 284 | { 285 | keySortSelector_ = keySortSelector; 286 | } 287 | 288 | sortsKeys_ = keySortSelector_ != NULL; 289 | usesComparatorForKeys_ = keySortSelector_ == NULL; 290 | } 291 | 292 | - (void)setObjectSortSelector:(SEL)objectSortSelector 293 | { 294 | if (objectSortSelector != objectSortSelector_) 295 | { 296 | objectSortSelector_ = objectSortSelector; 297 | } 298 | 299 | sortsObjects_ = objectSortSelector_ != NULL; 300 | usesComparatorForObjects_ = objectSortComparator_ == NULL; 301 | } 302 | 303 | - (void)setKeySortComparator:(NSComparator)keySortComparator 304 | { 305 | if (keySortComparator != keySortComparator_) 306 | { 307 | [keySortComparator_ release]; 308 | keySortComparator_ = Block_copy(keySortComparator); 309 | } 310 | 311 | sortsKeys_ = keySortComparator != nil; 312 | } 313 | 314 | - (void)setObjectSortComparator:(NSComparator)objectSortComparator 315 | { 316 | if (objectSortComparator != objectSortComparator_) 317 | { 318 | [objectSortComparator_ release]; 319 | objectSortComparator_ = Block_copy(objectSortComparator); 320 | } 321 | 322 | sortsObjects_ = objectSortComparator != nil; 323 | } 324 | 325 | @end 326 | --------------------------------------------------------------------------------