├── Example ├── TTTRandomizedEnumerator-Prefix.pch └── main.m ├── LICENSE ├── README.md ├── TTTRandomizedEnumerator.podspec ├── TTTRandomizedEnumerator.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── TTTRandomizedEnumerator.xcworkspace └── contents.xcworkspacedata └── TTTRandomizedEnumerator ├── TTTRandomizedEnumerator.h └── TTTRandomizedEnumerator.m /Example/TTTRandomizedEnumerator-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #ifdef __OBJC__ 8 | #import 9 | #endif 10 | -------------------------------------------------------------------------------- /Example/main.m: -------------------------------------------------------------------------------- 1 | // main.m 2 | // 3 | // Copyright (c) 2013 Mattt Thompson (http://mattt.me) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | 25 | #import "TTTRandomizedEnumerator.h" 26 | 27 | int main(int argc, const char * argv[]) { 28 | @autoreleasepool { 29 | NSUInteger capacity = 100; 30 | NSMutableArray *mutableNumbers = [NSMutableArray arrayWithCapacity:capacity]; 31 | for (NSUInteger i = 0; i < capacity; i++) { 32 | [mutableNumbers addObject:@(i)]; 33 | } 34 | 35 | for (NSNumber *number in [mutableNumbers randomizedObjectEnumerator]) { 36 | NSLog(@"%@", number); 37 | } 38 | } 39 | 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 Mattt Thompson (http://mattt.me/) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | TTTRandomizedEnumerator 2 | ======= 3 | **Random Access (Collection) Memories** 4 | 5 | Mix things up in your collection classes with style and class (well, a category, but you get the idea). 6 | 7 | I think we can all make a little more room in our hearts for `NSEnumerator`, that fresh jam from 1995. 8 | 9 | > Random aside: did you know you can reverse an `NSArray` in a single line with `NSEnumerator`? `array.reverseObjectEnumerator.allObjects`. Boom. 10 | 11 | Anyway, this is the best way to randomly step through the objects of an `NSArray`, `NSSet`, or `NSOrderedSet`, as well as the keys and values of an `NSDictionary`. 12 | 13 | ## Example Usage 14 | 15 | ```objective-c 16 | #import "TTTRandomizedEnumerator.h" 17 | 18 | NSUInteger capacity = 100; 19 | NSMutableArray *mutableNumbers = [NSMutableArray arrayWithCapacity:capacity]; 20 | for (NSUInteger i = 0; i < capacity; i++) { 21 | [mutableNumbers addObject:@(i)]; 22 | } 23 | 24 | // Classic `NSEnumerator` use with `while` loop 25 | NSNumber *number = nil; 26 | NSEnumerator *enumerator = [mutableNumbers randomizedObjectEnumerator]; 27 | while ((number = [enumerator nextObject])) { 28 | NSLog(@"%@", number); 29 | } 30 | 31 | // `NSEnumerator` also conforms to `` 32 | for (NSNumber *number in [mutableNumbers randomizedObjectEnumerator]) { 33 | NSLog(@"%@", number); 34 | } 35 | ``` 36 | 37 | ## Category Methods 38 | 39 | ### `NSArray` 40 | 41 | ```objective-c 42 | - (NSEnumerator *)randomizedObjectEnumerator; 43 | ``` 44 | 45 | ### `NSSet` 46 | 47 | ```objective-c 48 | - (NSEnumerator *)randomizedObjectEnumerator; 49 | ``` 50 | 51 | ### `NSOrderedSet` 52 | 53 | ```objective-c 54 | - (NSEnumerator *)randomizedObjectEnumerator; 55 | ``` 56 | 57 | ### `NSDictionary` 58 | 59 | ```objective-c 60 | - (NSEnumerator *)randomizedKeyEnumerator; 61 | - (NSEnumerator *)randomizedObjectEnumerator; 62 | ``` 63 | 64 | ## Contact 65 | 66 | Mattt Thompson 67 | 68 | - http://github.com/mattt 69 | - http://twitter.com/mattt 70 | - m@mattt.me 71 | 72 | ## License 73 | 74 | TTTRandomizedEnumerator is available under the MIT license. See the LICENSE file for more info. 75 | -------------------------------------------------------------------------------- /TTTRandomizedEnumerator.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'TTTRandomizedEnumerator' 3 | s.version = '0.0.3' 4 | s.license = 'MIT' 5 | s.summary = 'Mix things up in your collection classes with style and class (well, a category, but you get the idea).' 6 | s.homepage = 'https://github.com/mattt/TTTRandomizedEnumerator' 7 | s.social_media_url = 'https://twitter.com/mattt' 8 | s.authors = { 'Mattt Thompson' => 'm@mattt.me' } 9 | s.source = { :git => 'https://github.com/mattt/TTTRandomizedEnumerator.git', :tag => '0.0.3' } 10 | s.source_files = 'TTTRandomizedEnumerator' 11 | s.requires_arc = true 12 | end 13 | -------------------------------------------------------------------------------- /TTTRandomizedEnumerator.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | F8BEC953177FA811001005D2 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8BEC952177FA811001005D2 /* Foundation.framework */; }; 11 | F8BEC956177FA811001005D2 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = F8BEC955177FA811001005D2 /* main.m */; }; 12 | F8BEC962177FA825001005D2 /* TTTRandomizedEnumerator.m in Sources */ = {isa = PBXBuildFile; fileRef = F8BEC961177FA825001005D2 /* TTTRandomizedEnumerator.m */; }; 13 | /* End PBXBuildFile section */ 14 | 15 | /* Begin PBXCopyFilesBuildPhase section */ 16 | F8BEC94D177FA811001005D2 /* 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 | F8BEC94F177FA811001005D2 /* TTTRandomizedEnumerator */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = TTTRandomizedEnumerator; sourceTree = BUILT_PRODUCTS_DIR; }; 29 | F8BEC952177FA811001005D2 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 30 | F8BEC955177FA811001005D2 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = main.m; path = ../Example/main.m; sourceTree = ""; }; 31 | F8BEC958177FA811001005D2 /* TTTRandomizedEnumerator-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "TTTRandomizedEnumerator-Prefix.pch"; path = "../Example/TTTRandomizedEnumerator-Prefix.pch"; sourceTree = ""; }; 32 | F8BEC960177FA825001005D2 /* TTTRandomizedEnumerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TTTRandomizedEnumerator.h; sourceTree = ""; }; 33 | F8BEC961177FA825001005D2 /* TTTRandomizedEnumerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTTRandomizedEnumerator.m; sourceTree = ""; }; 34 | /* End PBXFileReference section */ 35 | 36 | /* Begin PBXFrameworksBuildPhase section */ 37 | F8BEC94C177FA811001005D2 /* Frameworks */ = { 38 | isa = PBXFrameworksBuildPhase; 39 | buildActionMask = 2147483647; 40 | files = ( 41 | F8BEC953177FA811001005D2 /* Foundation.framework in Frameworks */, 42 | ); 43 | runOnlyForDeploymentPostprocessing = 0; 44 | }; 45 | /* End PBXFrameworksBuildPhase section */ 46 | 47 | /* Begin PBXGroup section */ 48 | F8BEC946177FA811001005D2 = { 49 | isa = PBXGroup; 50 | children = ( 51 | F8BEC954177FA811001005D2 /* TTTRandomizedEnumerator */, 52 | F8BEC951177FA811001005D2 /* Frameworks */, 53 | F8BEC950177FA811001005D2 /* Products */, 54 | F8BEC963177FAD29001005D2 /* Vendor */, 55 | ); 56 | sourceTree = ""; 57 | }; 58 | F8BEC950177FA811001005D2 /* Products */ = { 59 | isa = PBXGroup; 60 | children = ( 61 | F8BEC94F177FA811001005D2 /* TTTRandomizedEnumerator */, 62 | ); 63 | name = Products; 64 | sourceTree = ""; 65 | }; 66 | F8BEC951177FA811001005D2 /* Frameworks */ = { 67 | isa = PBXGroup; 68 | children = ( 69 | F8BEC952177FA811001005D2 /* Foundation.framework */, 70 | ); 71 | name = Frameworks; 72 | sourceTree = ""; 73 | }; 74 | F8BEC954177FA811001005D2 /* TTTRandomizedEnumerator */ = { 75 | isa = PBXGroup; 76 | children = ( 77 | F8BEC955177FA811001005D2 /* main.m */, 78 | F8BEC957177FA811001005D2 /* Supporting Files */, 79 | ); 80 | path = TTTRandomizedEnumerator; 81 | sourceTree = ""; 82 | }; 83 | F8BEC957177FA811001005D2 /* Supporting Files */ = { 84 | isa = PBXGroup; 85 | children = ( 86 | F8BEC958177FA811001005D2 /* TTTRandomizedEnumerator-Prefix.pch */, 87 | ); 88 | name = "Supporting Files"; 89 | sourceTree = ""; 90 | }; 91 | F8BEC963177FAD29001005D2 /* Vendor */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | F8BEC964177FAD4E001005D2 /* TTTRandomizedEnumerator */, 95 | ); 96 | name = Vendor; 97 | path = TTTRandomizedEnumerator; 98 | sourceTree = ""; 99 | }; 100 | F8BEC964177FAD4E001005D2 /* TTTRandomizedEnumerator */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | F8BEC960177FA825001005D2 /* TTTRandomizedEnumerator.h */, 104 | F8BEC961177FA825001005D2 /* TTTRandomizedEnumerator.m */, 105 | ); 106 | name = TTTRandomizedEnumerator; 107 | sourceTree = ""; 108 | }; 109 | /* End PBXGroup section */ 110 | 111 | /* Begin PBXNativeTarget section */ 112 | F8BEC94E177FA811001005D2 /* TTTRandomizedEnumerator */ = { 113 | isa = PBXNativeTarget; 114 | buildConfigurationList = F8BEC95D177FA811001005D2 /* Build configuration list for PBXNativeTarget "TTTRandomizedEnumerator" */; 115 | buildPhases = ( 116 | F8BEC94B177FA811001005D2 /* Sources */, 117 | F8BEC94C177FA811001005D2 /* Frameworks */, 118 | F8BEC94D177FA811001005D2 /* CopyFiles */, 119 | ); 120 | buildRules = ( 121 | ); 122 | dependencies = ( 123 | ); 124 | name = TTTRandomizedEnumerator; 125 | productName = TTTRandomizedEnumerator; 126 | productReference = F8BEC94F177FA811001005D2 /* TTTRandomizedEnumerator */; 127 | productType = "com.apple.product-type.tool"; 128 | }; 129 | /* End PBXNativeTarget section */ 130 | 131 | /* Begin PBXProject section */ 132 | F8BEC947177FA811001005D2 /* Project object */ = { 133 | isa = PBXProject; 134 | attributes = { 135 | LastUpgradeCheck = 0500; 136 | ORGANIZATIONNAME = "Mattt Thompson"; 137 | }; 138 | buildConfigurationList = F8BEC94A177FA811001005D2 /* Build configuration list for PBXProject "TTTRandomizedEnumerator" */; 139 | compatibilityVersion = "Xcode 3.2"; 140 | developmentRegion = English; 141 | hasScannedForEncodings = 0; 142 | knownRegions = ( 143 | en, 144 | ); 145 | mainGroup = F8BEC946177FA811001005D2; 146 | productRefGroup = F8BEC950177FA811001005D2 /* Products */; 147 | projectDirPath = ""; 148 | projectRoot = ""; 149 | targets = ( 150 | F8BEC94E177FA811001005D2 /* TTTRandomizedEnumerator */, 151 | ); 152 | }; 153 | /* End PBXProject section */ 154 | 155 | /* Begin PBXSourcesBuildPhase section */ 156 | F8BEC94B177FA811001005D2 /* Sources */ = { 157 | isa = PBXSourcesBuildPhase; 158 | buildActionMask = 2147483647; 159 | files = ( 160 | F8BEC956177FA811001005D2 /* main.m in Sources */, 161 | F8BEC962177FA825001005D2 /* TTTRandomizedEnumerator.m in Sources */, 162 | ); 163 | runOnlyForDeploymentPostprocessing = 0; 164 | }; 165 | /* End PBXSourcesBuildPhase section */ 166 | 167 | /* Begin XCBuildConfiguration section */ 168 | F8BEC95B177FA811001005D2 /* Debug */ = { 169 | isa = XCBuildConfiguration; 170 | buildSettings = { 171 | ALWAYS_SEARCH_USER_PATHS = NO; 172 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 173 | CLANG_CXX_LIBRARY = "libc++"; 174 | CLANG_ENABLE_MODULES = YES; 175 | CLANG_ENABLE_OBJC_ARC = YES; 176 | CLANG_WARN_BOOL_CONVERSION = YES; 177 | CLANG_WARN_CONSTANT_CONVERSION = YES; 178 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 179 | CLANG_WARN_EMPTY_BODY = YES; 180 | CLANG_WARN_ENUM_CONVERSION = YES; 181 | CLANG_WARN_INT_CONVERSION = YES; 182 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 183 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 184 | COPY_PHASE_STRIP = NO; 185 | GCC_C_LANGUAGE_STANDARD = gnu99; 186 | GCC_DYNAMIC_NO_PIC = NO; 187 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 188 | GCC_OPTIMIZATION_LEVEL = 0; 189 | GCC_PREPROCESSOR_DEFINITIONS = ( 190 | "DEBUG=1", 191 | "$(inherited)", 192 | ); 193 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 194 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 195 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 196 | GCC_WARN_UNDECLARED_SELECTOR = YES; 197 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 198 | GCC_WARN_UNUSED_FUNCTION = YES; 199 | GCC_WARN_UNUSED_VARIABLE = YES; 200 | MACOSX_DEPLOYMENT_TARGET = 10.8; 201 | ONLY_ACTIVE_ARCH = YES; 202 | SDKROOT = macosx; 203 | }; 204 | name = Debug; 205 | }; 206 | F8BEC95C177FA811001005D2 /* Release */ = { 207 | isa = XCBuildConfiguration; 208 | buildSettings = { 209 | ALWAYS_SEARCH_USER_PATHS = NO; 210 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 211 | CLANG_CXX_LIBRARY = "libc++"; 212 | CLANG_ENABLE_MODULES = YES; 213 | CLANG_ENABLE_OBJC_ARC = YES; 214 | CLANG_WARN_BOOL_CONVERSION = YES; 215 | CLANG_WARN_CONSTANT_CONVERSION = YES; 216 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 217 | CLANG_WARN_EMPTY_BODY = YES; 218 | CLANG_WARN_ENUM_CONVERSION = YES; 219 | CLANG_WARN_INT_CONVERSION = YES; 220 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 221 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 222 | COPY_PHASE_STRIP = YES; 223 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 224 | ENABLE_NS_ASSERTIONS = NO; 225 | GCC_C_LANGUAGE_STANDARD = gnu99; 226 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 227 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 228 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 229 | GCC_WARN_UNDECLARED_SELECTOR = YES; 230 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 231 | GCC_WARN_UNUSED_FUNCTION = YES; 232 | GCC_WARN_UNUSED_VARIABLE = YES; 233 | MACOSX_DEPLOYMENT_TARGET = 10.8; 234 | SDKROOT = macosx; 235 | }; 236 | name = Release; 237 | }; 238 | F8BEC95E177FA811001005D2 /* Debug */ = { 239 | isa = XCBuildConfiguration; 240 | buildSettings = { 241 | ARCHS = "$(NATIVE_ARCH_ACTUAL)"; 242 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 243 | GCC_PREFIX_HEADER = "Example/TTTRandomizedEnumerator-Prefix.pch"; 244 | PRODUCT_NAME = "$(TARGET_NAME)"; 245 | }; 246 | name = Debug; 247 | }; 248 | F8BEC95F177FA811001005D2 /* Release */ = { 249 | isa = XCBuildConfiguration; 250 | buildSettings = { 251 | ARCHS = "$(NATIVE_ARCH_ACTUAL)"; 252 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 253 | GCC_PREFIX_HEADER = "Example/TTTRandomizedEnumerator-Prefix.pch"; 254 | PRODUCT_NAME = "$(TARGET_NAME)"; 255 | }; 256 | name = Release; 257 | }; 258 | /* End XCBuildConfiguration section */ 259 | 260 | /* Begin XCConfigurationList section */ 261 | F8BEC94A177FA811001005D2 /* Build configuration list for PBXProject "TTTRandomizedEnumerator" */ = { 262 | isa = XCConfigurationList; 263 | buildConfigurations = ( 264 | F8BEC95B177FA811001005D2 /* Debug */, 265 | F8BEC95C177FA811001005D2 /* Release */, 266 | ); 267 | defaultConfigurationIsVisible = 0; 268 | defaultConfigurationName = Release; 269 | }; 270 | F8BEC95D177FA811001005D2 /* Build configuration list for PBXNativeTarget "TTTRandomizedEnumerator" */ = { 271 | isa = XCConfigurationList; 272 | buildConfigurations = ( 273 | F8BEC95E177FA811001005D2 /* Debug */, 274 | F8BEC95F177FA811001005D2 /* Release */, 275 | ); 276 | defaultConfigurationIsVisible = 0; 277 | defaultConfigurationName = Release; 278 | }; 279 | /* End XCConfigurationList section */ 280 | }; 281 | rootObject = F8BEC947177FA811001005D2 /* Project object */; 282 | } 283 | -------------------------------------------------------------------------------- /TTTRandomizedEnumerator.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TTTRandomizedEnumerator.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 9 | 10 | 12 | 13 | 14 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /TTTRandomizedEnumerator/TTTRandomizedEnumerator.h: -------------------------------------------------------------------------------- 1 | // TTTRandomizedEnumerator.h 2 | // 3 | // Copyright (c) 2013 Mattt Thompson (http://mattt.me) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import 24 | 25 | @interface TTTRandomizedEnumerator : NSEnumerator 26 | 27 | @end 28 | 29 | #pragma mark - 30 | 31 | @interface NSArray (TTTRandomizedEnumerator) 32 | 33 | - (NSEnumerator *)randomizedObjectEnumerator; 34 | 35 | @end 36 | 37 | #pragma mark - 38 | 39 | @interface NSSet (TTTRandomizedEnumerator) 40 | 41 | - (NSEnumerator *)randomizedObjectEnumerator; 42 | 43 | @end 44 | 45 | #pragma mark - 46 | 47 | @interface NSOrderedSet (TTTRandomizedEnumerator) 48 | 49 | - (NSEnumerator *)randomizedObjectEnumerator; 50 | 51 | @end 52 | 53 | #pragma mark - 54 | 55 | @interface NSDictionary (TTTRandomizedEnumerator) 56 | 57 | - (NSEnumerator *)randomizedKeyEnumerator; 58 | 59 | - (NSEnumerator *)randomizedObjectEnumerator; 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /TTTRandomizedEnumerator/TTTRandomizedEnumerator.m: -------------------------------------------------------------------------------- 1 | // TTTRandomizedEnumerator.m 2 | // 3 | // Copyright (c) 2013 Mattt Thompson (http://mattt.me) 4 | // 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy 6 | // of this software and associated documentation files (the "Software"), to deal 7 | // in the Software without restriction, including without limitation the rights 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | // copies of the Software, and to permit persons to whom the Software is 10 | // furnished to do so, subject to the following conditions: 11 | // 12 | // The above copyright notice and this permission notice shall be included in 13 | // all copies or substantial portions of the Software. 14 | // 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | // THE SOFTWARE. 22 | 23 | #import "TTTRandomizedEnumerator.h" 24 | 25 | #import 26 | 27 | @interface TTTRandomizedEnumerator () { 28 | int32_t _idx; 29 | } 30 | 31 | @property (readwrite, nonatomic, strong) NSArray *objects; 32 | 33 | - (id)initWithObjects:(NSArray *)objects; 34 | 35 | @end 36 | 37 | @implementation TTTRandomizedEnumerator 38 | 39 | - (id)initWithObjects:(NSArray *)objects { 40 | self = [super init]; 41 | if (!self) { 42 | return nil; 43 | } 44 | 45 | NSMutableArray *mutableObjects = [NSMutableArray arrayWithArray:objects]; 46 | NSUInteger count = [mutableObjects count]; 47 | // See http://en.wikipedia.org/wiki/Fisher–Yates_shuffle 48 | if (count > 1) { 49 | for (NSUInteger i = count - 1; i > 0; --i) { 50 | [mutableObjects exchangeObjectAtIndex:i withObjectAtIndex:arc4random_uniform((int32_t)(i + 1))]; 51 | } 52 | } 53 | self.objects = mutableObjects; 54 | 55 | return self; 56 | } 57 | 58 | #pragma mark NSEnumerator 59 | 60 | - (NSArray *)allObjects { 61 | NSUInteger idx = _idx; 62 | if (idx < [self.objects count]) { 63 | _idx = (int32_t)[self.objects count]; 64 | return [self.objects subarrayWithRange:NSMakeRange(idx, [self.objects count] - idx)]; 65 | } 66 | 67 | return nil; 68 | } 69 | 70 | - (id)nextObject { 71 | NSUInteger idx = _idx; 72 | if (idx < [self.objects count]) { 73 | OSAtomicIncrement32(&_idx); 74 | return [self.objects objectAtIndex:idx]; 75 | } 76 | 77 | return nil; 78 | } 79 | 80 | @end 81 | 82 | #pragma mark - 83 | 84 | @implementation NSArray (TTTRandomizedEnumerator) 85 | 86 | - (NSEnumerator *)randomizedObjectEnumerator { 87 | return [[TTTRandomizedEnumerator alloc] initWithObjects:self]; 88 | } 89 | 90 | @end 91 | 92 | #pragma mark - 93 | 94 | @implementation NSSet (TTTRandomizedEnumerator) 95 | 96 | - (NSEnumerator *)randomizedObjectEnumerator { 97 | return [[TTTRandomizedEnumerator alloc] initWithObjects:[self allObjects]]; 98 | } 99 | 100 | @end 101 | 102 | #pragma mark - 103 | 104 | @implementation NSOrderedSet (TTTRandomizedEnumerator) 105 | 106 | - (NSEnumerator *)randomizedObjectEnumerator { 107 | return [[TTTRandomizedEnumerator alloc] initWithObjects:[self array]]; 108 | } 109 | 110 | @end 111 | 112 | #pragma mark - 113 | 114 | @implementation NSDictionary (TTTRandomizedEnumerator) 115 | 116 | - (NSEnumerator *)randomizedKeyEnumerator { 117 | return [[TTTRandomizedEnumerator alloc] initWithObjects:[self allKeys]]; 118 | } 119 | 120 | - (NSEnumerator *)randomizedObjectEnumerator { 121 | return [[TTTRandomizedEnumerator alloc] initWithObjects:[self allValues]]; 122 | } 123 | 124 | @end 125 | --------------------------------------------------------------------------------