├── .gitignore ├── GHODictionary iOS ├── GHODictionary iOS.h └── Info.plist ├── GHODictionary.podspec ├── GHODictionary.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcshareddata │ └── xcschemes │ ├── GHODictionary iOS.xcscheme │ └── GHODictionary.xcscheme ├── GHODictionary ├── GHODict.m ├── Info.plist └── include │ ├── GHODict.h │ └── GHODictionary.h ├── GHODictionaryTests ├── GHODictionaryTests.m └── Info.plist ├── LICENSE ├── Package.swift └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | # CocoaPods 21 | # 22 | # We recommend against adding the Pods directory to your .gitignore. However 23 | # you should judge for yourself, the pros and cons are mentioned at: 24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 25 | # 26 | #Pods/ 27 | 28 | 29 | # Swift Package Manager 30 | # 31 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 32 | # Packages/ 33 | # Package.pins 34 | # Package.resolved 35 | # *.xcodeproj 36 | # 37 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata 38 | # hence it is not needed unless you have added a package configuration file to your project 39 | .swiftpm 40 | 41 | .build/ 42 | -------------------------------------------------------------------------------- /GHODictionary iOS/GHODictionary iOS.h: -------------------------------------------------------------------------------- 1 | // 2 | // GHODictionary iOS.h 3 | // GHODictionary iOS 4 | // 5 | // Created by Pronk on 02/06/16. 6 | // Copyright © 2016 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for GHODictionary iOS. 12 | FOUNDATION_EXPORT double GHODictionary_iOSVersionNumber; 13 | 14 | //! Project version string for GHODictionary iOS. 15 | FOUNDATION_EXPORT const unsigned char GHODictionary_iOSVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /GHODictionary iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /GHODictionary.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | 3 | s.name = "GHODictionary" 4 | s.version = "1.1.1" 5 | s.summary = "Ordered dictionary." 6 | s.homepage = "https://github.com/gabriel/GHODictionary" 7 | s.license = { :type => "MIT" } 8 | s.author = { "Gabriel Handford" => "gabrielh@gmail.com" } 9 | s.source = { :git => "https://github.com/gabriel/GHODictionary.git", :tag => s.version.to_s } 10 | s.requires_arc = true 11 | s.source_files = "GHODictionary/**/*.{c,h,m}" 12 | 13 | s.ios.deployment_target = "7.0" 14 | 15 | s.tvos.deployment_target = "10.0" 16 | 17 | s.osx.deployment_target = "10.8" 18 | 19 | end 20 | -------------------------------------------------------------------------------- /GHODictionary.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 001391ED1B04112B0082DEA8 /* GHODictionary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 001391E11B04112B0082DEA8 /* GHODictionary.framework */; }; 11 | 001391F41B04112B0082DEA8 /* GHODictionaryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 001391F31B04112B0082DEA8 /* GHODictionaryTests.m */; }; 12 | 001392001B0411570082DEA8 /* GHODict.m in Sources */ = {isa = PBXBuildFile; fileRef = 001391FE1B0411560082DEA8 /* GHODict.m */; }; 13 | 33220B7C1CFF9F4600F3C3DA /* GHODict.m in Sources */ = {isa = PBXBuildFile; fileRef = 001391FE1B0411560082DEA8 /* GHODict.m */; }; 14 | D939A20826949F9100581864 /* GHODictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = D939A20626949F9100581864 /* GHODictionary.h */; settings = {ATTRIBUTES = (Public, ); }; }; 15 | D939A20926949FD900581864 /* GHODict.h in Headers */ = {isa = PBXBuildFile; fileRef = D939A20526949F9100581864 /* GHODict.h */; settings = {ATTRIBUTES = (Public, ); }; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXContainerItemProxy section */ 19 | 001391EE1B04112B0082DEA8 /* PBXContainerItemProxy */ = { 20 | isa = PBXContainerItemProxy; 21 | containerPortal = 001391D81B04112B0082DEA8 /* Project object */; 22 | proxyType = 1; 23 | remoteGlobalIDString = 001391E01B04112B0082DEA8; 24 | remoteInfo = GHODictionary; 25 | }; 26 | /* End PBXContainerItemProxy section */ 27 | 28 | /* Begin PBXFileReference section */ 29 | 001391E11B04112B0082DEA8 /* GHODictionary.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = GHODictionary.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 30 | 001391E51B04112B0082DEA8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 31 | 001391EC1B04112B0082DEA8 /* GHODictionaryTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GHODictionaryTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 32 | 001391F21B04112B0082DEA8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 33 | 001391F31B04112B0082DEA8 /* GHODictionaryTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GHODictionaryTests.m; sourceTree = ""; }; 34 | 001391FE1B0411560082DEA8 /* GHODict.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GHODict.m; sourceTree = ""; }; 35 | 001392011B0411D30082DEA8 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 36 | 001392021B0412160082DEA8 /* GHODictionary.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = GHODictionary.podspec; sourceTree = ""; }; 37 | 33220B721CFF9F1700F3C3DA /* GHODictionary.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = GHODictionary.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 38 | 33220B761CFF9F1700F3C3DA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 39 | D939A20526949F9100581864 /* GHODict.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GHODict.h; sourceTree = ""; }; 40 | D939A20626949F9100581864 /* GHODictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GHODictionary.h; sourceTree = ""; }; 41 | /* End PBXFileReference section */ 42 | 43 | /* Begin PBXFrameworksBuildPhase section */ 44 | 001391DD1B04112B0082DEA8 /* Frameworks */ = { 45 | isa = PBXFrameworksBuildPhase; 46 | buildActionMask = 2147483647; 47 | files = ( 48 | ); 49 | runOnlyForDeploymentPostprocessing = 0; 50 | }; 51 | 001391E91B04112B0082DEA8 /* Frameworks */ = { 52 | isa = PBXFrameworksBuildPhase; 53 | buildActionMask = 2147483647; 54 | files = ( 55 | 001391ED1B04112B0082DEA8 /* GHODictionary.framework in Frameworks */, 56 | ); 57 | runOnlyForDeploymentPostprocessing = 0; 58 | }; 59 | 33220B6E1CFF9F1700F3C3DA /* Frameworks */ = { 60 | isa = PBXFrameworksBuildPhase; 61 | buildActionMask = 2147483647; 62 | files = ( 63 | ); 64 | runOnlyForDeploymentPostprocessing = 0; 65 | }; 66 | /* End PBXFrameworksBuildPhase section */ 67 | 68 | /* Begin PBXGroup section */ 69 | 001391D71B04112B0082DEA8 = { 70 | isa = PBXGroup; 71 | children = ( 72 | 001392011B0411D30082DEA8 /* README.md */, 73 | 001392021B0412160082DEA8 /* GHODictionary.podspec */, 74 | 001391E31B04112B0082DEA8 /* GHODictionary */, 75 | 001391F01B04112B0082DEA8 /* GHODictionaryTests */, 76 | 33220B731CFF9F1700F3C3DA /* GHODictionary iOS */, 77 | 001391E21B04112B0082DEA8 /* Products */, 78 | ); 79 | sourceTree = ""; 80 | }; 81 | 001391E21B04112B0082DEA8 /* Products */ = { 82 | isa = PBXGroup; 83 | children = ( 84 | 001391E11B04112B0082DEA8 /* GHODictionary.framework */, 85 | 001391EC1B04112B0082DEA8 /* GHODictionaryTests.xctest */, 86 | 33220B721CFF9F1700F3C3DA /* GHODictionary.framework */, 87 | ); 88 | name = Products; 89 | sourceTree = ""; 90 | }; 91 | 001391E31B04112B0082DEA8 /* GHODictionary */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | D939A20426949F9100581864 /* include */, 95 | 001391E41B04112B0082DEA8 /* Supporting Files */, 96 | 001391FE1B0411560082DEA8 /* GHODict.m */, 97 | ); 98 | path = GHODictionary; 99 | sourceTree = ""; 100 | }; 101 | 001391E41B04112B0082DEA8 /* Supporting Files */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | 001391E51B04112B0082DEA8 /* Info.plist */, 105 | ); 106 | name = "Supporting Files"; 107 | sourceTree = ""; 108 | }; 109 | 001391F01B04112B0082DEA8 /* GHODictionaryTests */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | 001391F31B04112B0082DEA8 /* GHODictionaryTests.m */, 113 | 001391F11B04112B0082DEA8 /* Supporting Files */, 114 | ); 115 | path = GHODictionaryTests; 116 | sourceTree = ""; 117 | }; 118 | 001391F11B04112B0082DEA8 /* Supporting Files */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | 001391F21B04112B0082DEA8 /* Info.plist */, 122 | ); 123 | name = "Supporting Files"; 124 | sourceTree = ""; 125 | }; 126 | 33220B731CFF9F1700F3C3DA /* GHODictionary iOS */ = { 127 | isa = PBXGroup; 128 | children = ( 129 | 33220B761CFF9F1700F3C3DA /* Info.plist */, 130 | ); 131 | path = "GHODictionary iOS"; 132 | sourceTree = ""; 133 | }; 134 | D939A20426949F9100581864 /* include */ = { 135 | isa = PBXGroup; 136 | children = ( 137 | D939A20526949F9100581864 /* GHODict.h */, 138 | D939A20626949F9100581864 /* GHODictionary.h */, 139 | ); 140 | path = include; 141 | sourceTree = ""; 142 | }; 143 | /* End PBXGroup section */ 144 | 145 | /* Begin PBXHeadersBuildPhase section */ 146 | 001391DE1B04112B0082DEA8 /* Headers */ = { 147 | isa = PBXHeadersBuildPhase; 148 | buildActionMask = 2147483647; 149 | files = ( 150 | D939A20826949F9100581864 /* GHODictionary.h in Headers */, 151 | D939A20926949FD900581864 /* GHODict.h in Headers */, 152 | ); 153 | runOnlyForDeploymentPostprocessing = 0; 154 | }; 155 | 33220B6F1CFF9F1700F3C3DA /* Headers */ = { 156 | isa = PBXHeadersBuildPhase; 157 | buildActionMask = 2147483647; 158 | files = ( 159 | ); 160 | runOnlyForDeploymentPostprocessing = 0; 161 | }; 162 | /* End PBXHeadersBuildPhase section */ 163 | 164 | /* Begin PBXNativeTarget section */ 165 | 001391E01B04112B0082DEA8 /* GHODictionary */ = { 166 | isa = PBXNativeTarget; 167 | buildConfigurationList = 001391F71B04112B0082DEA8 /* Build configuration list for PBXNativeTarget "GHODictionary" */; 168 | buildPhases = ( 169 | 001391DC1B04112B0082DEA8 /* Sources */, 170 | 001391DD1B04112B0082DEA8 /* Frameworks */, 171 | 001391DE1B04112B0082DEA8 /* Headers */, 172 | 001391DF1B04112B0082DEA8 /* Resources */, 173 | ); 174 | buildRules = ( 175 | ); 176 | dependencies = ( 177 | ); 178 | name = GHODictionary; 179 | productName = GHODictionary; 180 | productReference = 001391E11B04112B0082DEA8 /* GHODictionary.framework */; 181 | productType = "com.apple.product-type.framework"; 182 | }; 183 | 001391EB1B04112B0082DEA8 /* GHODictionaryTests */ = { 184 | isa = PBXNativeTarget; 185 | buildConfigurationList = 001391FA1B04112B0082DEA8 /* Build configuration list for PBXNativeTarget "GHODictionaryTests" */; 186 | buildPhases = ( 187 | 001391E81B04112B0082DEA8 /* Sources */, 188 | 001391E91B04112B0082DEA8 /* Frameworks */, 189 | 001391EA1B04112B0082DEA8 /* Resources */, 190 | ); 191 | buildRules = ( 192 | ); 193 | dependencies = ( 194 | 001391EF1B04112B0082DEA8 /* PBXTargetDependency */, 195 | ); 196 | name = GHODictionaryTests; 197 | productName = GHODictionaryTests; 198 | productReference = 001391EC1B04112B0082DEA8 /* GHODictionaryTests.xctest */; 199 | productType = "com.apple.product-type.bundle.unit-test"; 200 | }; 201 | 33220B711CFF9F1700F3C3DA /* GHODictionary iOS */ = { 202 | isa = PBXNativeTarget; 203 | buildConfigurationList = 33220B791CFF9F1700F3C3DA /* Build configuration list for PBXNativeTarget "GHODictionary iOS" */; 204 | buildPhases = ( 205 | 33220B6D1CFF9F1700F3C3DA /* Sources */, 206 | 33220B6E1CFF9F1700F3C3DA /* Frameworks */, 207 | 33220B6F1CFF9F1700F3C3DA /* Headers */, 208 | 33220B701CFF9F1700F3C3DA /* Resources */, 209 | ); 210 | buildRules = ( 211 | ); 212 | dependencies = ( 213 | ); 214 | name = "GHODictionary iOS"; 215 | productName = "GHODictionary iOS"; 216 | productReference = 33220B721CFF9F1700F3C3DA /* GHODictionary.framework */; 217 | productType = "com.apple.product-type.framework"; 218 | }; 219 | /* End PBXNativeTarget section */ 220 | 221 | /* Begin PBXProject section */ 222 | 001391D81B04112B0082DEA8 /* Project object */ = { 223 | isa = PBXProject; 224 | attributes = { 225 | LastUpgradeCheck = 0630; 226 | ORGANIZATIONNAME = "Gabriel Handford"; 227 | TargetAttributes = { 228 | 001391E01B04112B0082DEA8 = { 229 | CreatedOnToolsVersion = 6.3.1; 230 | }; 231 | 001391EB1B04112B0082DEA8 = { 232 | CreatedOnToolsVersion = 6.3.1; 233 | }; 234 | 33220B711CFF9F1700F3C3DA = { 235 | CreatedOnToolsVersion = 7.3.1; 236 | DevelopmentTeam = 7ZVA8A38DQ; 237 | }; 238 | }; 239 | }; 240 | buildConfigurationList = 001391DB1B04112B0082DEA8 /* Build configuration list for PBXProject "GHODictionary" */; 241 | compatibilityVersion = "Xcode 3.2"; 242 | developmentRegion = English; 243 | hasScannedForEncodings = 0; 244 | knownRegions = ( 245 | English, 246 | en, 247 | ); 248 | mainGroup = 001391D71B04112B0082DEA8; 249 | productRefGroup = 001391E21B04112B0082DEA8 /* Products */; 250 | projectDirPath = ""; 251 | projectRoot = ""; 252 | targets = ( 253 | 001391E01B04112B0082DEA8 /* GHODictionary */, 254 | 001391EB1B04112B0082DEA8 /* GHODictionaryTests */, 255 | 33220B711CFF9F1700F3C3DA /* GHODictionary iOS */, 256 | ); 257 | }; 258 | /* End PBXProject section */ 259 | 260 | /* Begin PBXResourcesBuildPhase section */ 261 | 001391DF1B04112B0082DEA8 /* Resources */ = { 262 | isa = PBXResourcesBuildPhase; 263 | buildActionMask = 2147483647; 264 | files = ( 265 | ); 266 | runOnlyForDeploymentPostprocessing = 0; 267 | }; 268 | 001391EA1B04112B0082DEA8 /* Resources */ = { 269 | isa = PBXResourcesBuildPhase; 270 | buildActionMask = 2147483647; 271 | files = ( 272 | ); 273 | runOnlyForDeploymentPostprocessing = 0; 274 | }; 275 | 33220B701CFF9F1700F3C3DA /* Resources */ = { 276 | isa = PBXResourcesBuildPhase; 277 | buildActionMask = 2147483647; 278 | files = ( 279 | ); 280 | runOnlyForDeploymentPostprocessing = 0; 281 | }; 282 | /* End PBXResourcesBuildPhase section */ 283 | 284 | /* Begin PBXSourcesBuildPhase section */ 285 | 001391DC1B04112B0082DEA8 /* Sources */ = { 286 | isa = PBXSourcesBuildPhase; 287 | buildActionMask = 2147483647; 288 | files = ( 289 | 001392001B0411570082DEA8 /* GHODict.m in Sources */, 290 | ); 291 | runOnlyForDeploymentPostprocessing = 0; 292 | }; 293 | 001391E81B04112B0082DEA8 /* Sources */ = { 294 | isa = PBXSourcesBuildPhase; 295 | buildActionMask = 2147483647; 296 | files = ( 297 | 001391F41B04112B0082DEA8 /* GHODictionaryTests.m in Sources */, 298 | ); 299 | runOnlyForDeploymentPostprocessing = 0; 300 | }; 301 | 33220B6D1CFF9F1700F3C3DA /* Sources */ = { 302 | isa = PBXSourcesBuildPhase; 303 | buildActionMask = 2147483647; 304 | files = ( 305 | 33220B7C1CFF9F4600F3C3DA /* GHODict.m in Sources */, 306 | ); 307 | runOnlyForDeploymentPostprocessing = 0; 308 | }; 309 | /* End PBXSourcesBuildPhase section */ 310 | 311 | /* Begin PBXTargetDependency section */ 312 | 001391EF1B04112B0082DEA8 /* PBXTargetDependency */ = { 313 | isa = PBXTargetDependency; 314 | target = 001391E01B04112B0082DEA8 /* GHODictionary */; 315 | targetProxy = 001391EE1B04112B0082DEA8 /* PBXContainerItemProxy */; 316 | }; 317 | /* End PBXTargetDependency section */ 318 | 319 | /* Begin XCBuildConfiguration section */ 320 | 001391F51B04112B0082DEA8 /* Debug */ = { 321 | isa = XCBuildConfiguration; 322 | buildSettings = { 323 | ALWAYS_SEARCH_USER_PATHS = NO; 324 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 325 | CLANG_CXX_LIBRARY = "libc++"; 326 | CLANG_ENABLE_MODULES = YES; 327 | CLANG_ENABLE_OBJC_ARC = YES; 328 | CLANG_WARN_BOOL_CONVERSION = YES; 329 | CLANG_WARN_CONSTANT_CONVERSION = YES; 330 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 331 | CLANG_WARN_EMPTY_BODY = YES; 332 | CLANG_WARN_ENUM_CONVERSION = YES; 333 | CLANG_WARN_INT_CONVERSION = YES; 334 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 335 | CLANG_WARN_UNREACHABLE_CODE = YES; 336 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 337 | COPY_PHASE_STRIP = NO; 338 | CURRENT_PROJECT_VERSION = 1; 339 | DEBUG_INFORMATION_FORMAT = dwarf; 340 | ENABLE_STRICT_OBJC_MSGSEND = YES; 341 | GCC_C_LANGUAGE_STANDARD = gnu99; 342 | GCC_DYNAMIC_NO_PIC = NO; 343 | GCC_NO_COMMON_BLOCKS = YES; 344 | GCC_OPTIMIZATION_LEVEL = 0; 345 | GCC_PREPROCESSOR_DEFINITIONS = ( 346 | "DEBUG=1", 347 | "$(inherited)", 348 | ); 349 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 350 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 351 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 352 | GCC_WARN_UNDECLARED_SELECTOR = YES; 353 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 354 | GCC_WARN_UNUSED_FUNCTION = YES; 355 | GCC_WARN_UNUSED_VARIABLE = YES; 356 | MACOSX_DEPLOYMENT_TARGET = 10.10; 357 | MTL_ENABLE_DEBUG_INFO = YES; 358 | ONLY_ACTIVE_ARCH = YES; 359 | SDKROOT = macosx; 360 | VERSIONING_SYSTEM = "apple-generic"; 361 | VERSION_INFO_PREFIX = ""; 362 | }; 363 | name = Debug; 364 | }; 365 | 001391F61B04112B0082DEA8 /* Release */ = { 366 | isa = XCBuildConfiguration; 367 | buildSettings = { 368 | ALWAYS_SEARCH_USER_PATHS = NO; 369 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 370 | CLANG_CXX_LIBRARY = "libc++"; 371 | CLANG_ENABLE_MODULES = YES; 372 | CLANG_ENABLE_OBJC_ARC = YES; 373 | CLANG_WARN_BOOL_CONVERSION = YES; 374 | CLANG_WARN_CONSTANT_CONVERSION = YES; 375 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 376 | CLANG_WARN_EMPTY_BODY = YES; 377 | CLANG_WARN_ENUM_CONVERSION = YES; 378 | CLANG_WARN_INT_CONVERSION = YES; 379 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 380 | CLANG_WARN_UNREACHABLE_CODE = YES; 381 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 382 | COPY_PHASE_STRIP = NO; 383 | CURRENT_PROJECT_VERSION = 1; 384 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 385 | ENABLE_NS_ASSERTIONS = NO; 386 | ENABLE_STRICT_OBJC_MSGSEND = YES; 387 | GCC_C_LANGUAGE_STANDARD = gnu99; 388 | GCC_NO_COMMON_BLOCKS = YES; 389 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 390 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 391 | GCC_WARN_UNDECLARED_SELECTOR = YES; 392 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 393 | GCC_WARN_UNUSED_FUNCTION = YES; 394 | GCC_WARN_UNUSED_VARIABLE = YES; 395 | MACOSX_DEPLOYMENT_TARGET = 10.10; 396 | MTL_ENABLE_DEBUG_INFO = NO; 397 | SDKROOT = macosx; 398 | VERSIONING_SYSTEM = "apple-generic"; 399 | VERSION_INFO_PREFIX = ""; 400 | }; 401 | name = Release; 402 | }; 403 | 001391F81B04112B0082DEA8 /* Debug */ = { 404 | isa = XCBuildConfiguration; 405 | buildSettings = { 406 | COMBINE_HIDPI_IMAGES = YES; 407 | DEFINES_MODULE = YES; 408 | DYLIB_COMPATIBILITY_VERSION = 1; 409 | DYLIB_CURRENT_VERSION = 1; 410 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 411 | FRAMEWORK_VERSION = A; 412 | INFOPLIST_FILE = GHODictionary/Info.plist; 413 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 414 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 415 | PRODUCT_NAME = "$(TARGET_NAME)"; 416 | SKIP_INSTALL = YES; 417 | }; 418 | name = Debug; 419 | }; 420 | 001391F91B04112B0082DEA8 /* Release */ = { 421 | isa = XCBuildConfiguration; 422 | buildSettings = { 423 | COMBINE_HIDPI_IMAGES = YES; 424 | DEFINES_MODULE = YES; 425 | DYLIB_COMPATIBILITY_VERSION = 1; 426 | DYLIB_CURRENT_VERSION = 1; 427 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 428 | FRAMEWORK_VERSION = A; 429 | INFOPLIST_FILE = GHODictionary/Info.plist; 430 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 431 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 432 | PRODUCT_NAME = "$(TARGET_NAME)"; 433 | SKIP_INSTALL = YES; 434 | }; 435 | name = Release; 436 | }; 437 | 001391FB1B04112B0082DEA8 /* Debug */ = { 438 | isa = XCBuildConfiguration; 439 | buildSettings = { 440 | COMBINE_HIDPI_IMAGES = YES; 441 | FRAMEWORK_SEARCH_PATHS = ( 442 | "$(DEVELOPER_FRAMEWORKS_DIR)", 443 | "$(inherited)", 444 | ); 445 | GCC_PREPROCESSOR_DEFINITIONS = ( 446 | "DEBUG=1", 447 | "$(inherited)", 448 | ); 449 | INFOPLIST_FILE = GHODictionaryTests/Info.plist; 450 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 451 | PRODUCT_NAME = "$(TARGET_NAME)"; 452 | }; 453 | name = Debug; 454 | }; 455 | 001391FC1B04112B0082DEA8 /* Release */ = { 456 | isa = XCBuildConfiguration; 457 | buildSettings = { 458 | COMBINE_HIDPI_IMAGES = YES; 459 | FRAMEWORK_SEARCH_PATHS = ( 460 | "$(DEVELOPER_FRAMEWORKS_DIR)", 461 | "$(inherited)", 462 | ); 463 | INFOPLIST_FILE = GHODictionaryTests/Info.plist; 464 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 465 | PRODUCT_NAME = "$(TARGET_NAME)"; 466 | }; 467 | name = Release; 468 | }; 469 | 33220B771CFF9F1700F3C3DA /* Debug */ = { 470 | isa = XCBuildConfiguration; 471 | buildSettings = { 472 | CLANG_ANALYZER_NONNULL = YES; 473 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 474 | DEFINES_MODULE = YES; 475 | DYLIB_COMPATIBILITY_VERSION = 1; 476 | DYLIB_CURRENT_VERSION = 1; 477 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 478 | ENABLE_TESTABILITY = YES; 479 | INFOPLIST_FILE = "GHODictionary iOS/Info.plist"; 480 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 481 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 482 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 483 | PRODUCT_BUNDLE_IDENTIFIER = "me.rel.GHODictionary-iOS"; 484 | PRODUCT_NAME = GHODictionary; 485 | SDKROOT = iphoneos; 486 | SKIP_INSTALL = YES; 487 | TARGETED_DEVICE_FAMILY = "1,2"; 488 | }; 489 | name = Debug; 490 | }; 491 | 33220B781CFF9F1700F3C3DA /* Release */ = { 492 | isa = XCBuildConfiguration; 493 | buildSettings = { 494 | CLANG_ANALYZER_NONNULL = YES; 495 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 496 | DEFINES_MODULE = YES; 497 | DYLIB_COMPATIBILITY_VERSION = 1; 498 | DYLIB_CURRENT_VERSION = 1; 499 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 500 | INFOPLIST_FILE = "GHODictionary iOS/Info.plist"; 501 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 502 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 503 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 504 | PRODUCT_BUNDLE_IDENTIFIER = "me.rel.GHODictionary-iOS"; 505 | PRODUCT_NAME = GHODictionary; 506 | SDKROOT = iphoneos; 507 | SKIP_INSTALL = YES; 508 | TARGETED_DEVICE_FAMILY = "1,2"; 509 | VALIDATE_PRODUCT = YES; 510 | }; 511 | name = Release; 512 | }; 513 | /* End XCBuildConfiguration section */ 514 | 515 | /* Begin XCConfigurationList section */ 516 | 001391DB1B04112B0082DEA8 /* Build configuration list for PBXProject "GHODictionary" */ = { 517 | isa = XCConfigurationList; 518 | buildConfigurations = ( 519 | 001391F51B04112B0082DEA8 /* Debug */, 520 | 001391F61B04112B0082DEA8 /* Release */, 521 | ); 522 | defaultConfigurationIsVisible = 0; 523 | defaultConfigurationName = Release; 524 | }; 525 | 001391F71B04112B0082DEA8 /* Build configuration list for PBXNativeTarget "GHODictionary" */ = { 526 | isa = XCConfigurationList; 527 | buildConfigurations = ( 528 | 001391F81B04112B0082DEA8 /* Debug */, 529 | 001391F91B04112B0082DEA8 /* Release */, 530 | ); 531 | defaultConfigurationIsVisible = 0; 532 | defaultConfigurationName = Release; 533 | }; 534 | 001391FA1B04112B0082DEA8 /* Build configuration list for PBXNativeTarget "GHODictionaryTests" */ = { 535 | isa = XCConfigurationList; 536 | buildConfigurations = ( 537 | 001391FB1B04112B0082DEA8 /* Debug */, 538 | 001391FC1B04112B0082DEA8 /* Release */, 539 | ); 540 | defaultConfigurationIsVisible = 0; 541 | defaultConfigurationName = Release; 542 | }; 543 | 33220B791CFF9F1700F3C3DA /* Build configuration list for PBXNativeTarget "GHODictionary iOS" */ = { 544 | isa = XCConfigurationList; 545 | buildConfigurations = ( 546 | 33220B771CFF9F1700F3C3DA /* Debug */, 547 | 33220B781CFF9F1700F3C3DA /* Release */, 548 | ); 549 | defaultConfigurationIsVisible = 0; 550 | defaultConfigurationName = Release; 551 | }; 552 | /* End XCConfigurationList section */ 553 | }; 554 | rootObject = 001391D81B04112B0082DEA8 /* Project object */; 555 | } 556 | -------------------------------------------------------------------------------- /GHODictionary.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /GHODictionary.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /GHODictionary.xcodeproj/xcshareddata/xcschemes/GHODictionary iOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /GHODictionary.xcodeproj/xcshareddata/xcschemes/GHODictionary.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 94 | 100 | 101 | 102 | 103 | 105 | 106 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /GHODictionary/GHODict.m: -------------------------------------------------------------------------------- 1 | // 2 | // GHODict.m 3 | // GHODictionary 4 | // 5 | // Created by Gabriel on 5/13/15. 6 | // Copyright (c) 2015 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import "include/GHODict.h" 10 | 11 | @interface GHODictionary () 12 | @property NSMutableArray *array; 13 | @property NSMutableDictionary *dictionary; 14 | @end 15 | 16 | @implementation GHODictionary 17 | 18 | - (instancetype)init { 19 | return [self initWithCapacity:10]; 20 | } 21 | 22 | - (instancetype)initWithCapacity:(NSUInteger)capacity { 23 | if ((self = [super init])) { 24 | _array = [NSMutableArray arrayWithCapacity:capacity]; 25 | _dictionary = [NSMutableDictionary dictionaryWithCapacity:capacity]; 26 | } 27 | return self; 28 | } 29 | 30 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary { 31 | if ((self = [self initWithCapacity:[dictionary count]])) { 32 | [self addEntriesFromDictionary:dictionary]; 33 | } 34 | return self; 35 | } 36 | 37 | + (instancetype)dictionary { 38 | return [[self alloc] init]; 39 | } 40 | 41 | + (instancetype)dictionaryWithDictionary:(NSDictionary *)dictionary { 42 | return [[self alloc] initWithDictionary:dictionary]; 43 | } 44 | 45 | + (instancetype)dictionaryWithCapacity:(NSUInteger)capacity { 46 | return [[self alloc] initWithCapacity:capacity]; 47 | } 48 | 49 | + (instancetype)d:(NSDictionary *)dictionary { 50 | return [[self alloc] initWithDictionary:dictionary]; 51 | } 52 | 53 | - (id)mutableCopyWithZone:(NSZone *)zone { 54 | GHODictionary *mutableCopy = [[GHODictionary allocWithZone:zone] init]; 55 | mutableCopy.array = [_array mutableCopy]; 56 | mutableCopy.dictionary = [_dictionary mutableCopy]; 57 | return mutableCopy; 58 | } 59 | 60 | - (instancetype)copy { 61 | return [self mutableCopy]; 62 | } 63 | 64 | - (id)objectForKey:(id)key { 65 | return [_dictionary objectForKey:key]; 66 | } 67 | 68 | - (void)setObject:(id)object forKey:(id)key { 69 | if (!object) { 70 | [self removeObjectForKey:key]; 71 | return; 72 | } 73 | 74 | if (![_dictionary objectForKey:key]) { 75 | [_array addObject:key]; 76 | } 77 | [_dictionary setObject:object forKey:key]; 78 | } 79 | 80 | - (void)removeObjectForKey:(id)key { 81 | [_dictionary removeObjectForKey:key]; 82 | [_array removeObject:key]; 83 | } 84 | 85 | - (NSDictionary *)toDictionary { 86 | return [_dictionary copy]; 87 | } 88 | 89 | - (void)sortUsingSelector:(SEL)selector { 90 | [_array sortUsingSelector:selector]; 91 | } 92 | 93 | - (NSEnumerator *)keyEnumerator { 94 | return [_array objectEnumerator]; 95 | } 96 | 97 | - (NSEnumerator *)reverseKeyEnumerator { 98 | return [_array reverseObjectEnumerator]; 99 | } 100 | 101 | - (void)insertObject:(id)object forKey:(id)key atIndex:(NSUInteger)index { 102 | if ([_dictionary objectForKey:key]) { 103 | [self removeObjectForKey:key]; 104 | } 105 | [_array insertObject:key atIndex:index]; 106 | [self setObject:object forKey:key]; 107 | } 108 | 109 | - (id)keyAtIndex:(NSUInteger)index { 110 | return [_array objectAtIndex:index]; 111 | } 112 | 113 | - (void)setObject:(id)obj forKeyedSubscript:(id)key { 114 | [self setObject:obj forKey:key]; 115 | } 116 | 117 | - (id)objectForKeyedSubscript:(id)key { 118 | return [self objectForKey:key]; 119 | } 120 | 121 | - (NSInteger)count { 122 | return [_array count]; 123 | } 124 | 125 | - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id __unsafe_unretained [])buffer count:(NSUInteger)len { 126 | return [_array countByEnumeratingWithState:state objects:buffer count:len]; 127 | } 128 | 129 | - (void)sortKeysUsingSelector:(SEL)selector deepSort:(BOOL)deepSort { 130 | [_array sortUsingSelector:selector]; 131 | 132 | if (deepSort) { 133 | for (id key in _array) { 134 | id value = self[key]; 135 | if ([value respondsToSelector:@selector(sortKeysUsingSelector:deepSort:)]) { 136 | [value sortKeysUsingSelector:selector deepSort:deepSort]; 137 | } 138 | } 139 | } 140 | } 141 | 142 | - (NSArray *)allKeys { 143 | return _array; 144 | } 145 | 146 | - (void)addEntriesFromOrderedDictionary:(GHODictionary *)dictionary { 147 | [self addEntriesFromDictionary:dictionary]; 148 | } 149 | 150 | - (void)addEntriesFromDictionary:(id)dictionary { 151 | for (id key in dictionary) { 152 | if (![_dictionary objectForKey:key]) { 153 | [_array addObject:key]; 154 | } 155 | } 156 | NSDictionary *dict = [dictionary isKindOfClass:GHODictionary.class] ? [dictionary toDictionary] : dictionary; 157 | [_dictionary addEntriesFromDictionary:dict]; 158 | } 159 | 160 | - (void)addObject:(id)object forKey:(id)key { 161 | NSMutableArray *values = self[key]; 162 | if (!values) { 163 | values = [NSMutableArray array]; 164 | self[key] = values; 165 | } 166 | [values addObject:object]; 167 | } 168 | 169 | - (NSString *)description { 170 | NSMutableArray *lines = [NSMutableArray array]; 171 | [lines addObject:@"{"]; 172 | for (id key in self) { 173 | [lines addObject:[NSString stringWithFormat:@" %@: %@", key, self[key]]]; 174 | } 175 | [lines addObject:@"}"]; 176 | return [lines componentsJoinedByString:@"\n"]; 177 | } 178 | 179 | - (BOOL)isEqual:(id)object { 180 | if ([object isKindOfClass:GHODictionary.class]) { 181 | GHODictionary *dict = (GHODictionary *)object; 182 | return [[dict toDictionary] isEqual:_dictionary] && [[dict allKeys] isEqual:[self allKeys]]; 183 | } 184 | return NO; 185 | } 186 | 187 | - (NSUInteger)hash { 188 | return [_dictionary hash]; 189 | } 190 | 191 | - (NSArray *)map:(id (^)(id key, id value))block { 192 | NSMutableArray *array = [NSMutableArray array]; 193 | 194 | [self enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { 195 | id object = block(key, obj); 196 | if (object) { 197 | [array addObject:object]; 198 | } 199 | }]; 200 | 201 | return array; 202 | } 203 | 204 | - (void)enumerateKeysAndObjectsUsingBlock:(void (^)(id key, id obj, BOOL *stop))block { 205 | for (id key in _array) { 206 | BOOL stop = NO; 207 | block(key, _dictionary[key], &stop); 208 | if (stop) break; 209 | } 210 | } 211 | 212 | @end 213 | 214 | -------------------------------------------------------------------------------- /GHODictionary/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | me.rel.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSHumanReadableCopyright 24 | Copyright © 2015 Gabriel Handford. All rights reserved. 25 | NSPrincipalClass 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /GHODictionary/include/GHODict.h: -------------------------------------------------------------------------------- 1 | // 2 | // GHODict.h 3 | // GHODictionary 4 | // 5 | // Created by Gabriel on 5/13/15. 6 | // Copyright (c) 2015 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface GHODictionary : NSObject 12 | 13 | - (instancetype)initWithCapacity:(NSUInteger)capacity; 14 | - (instancetype)initWithDictionary:(NSDictionary *)dictionary; 15 | + (instancetype)dictionary; 16 | + (instancetype)dictionaryWithDictionary:(NSDictionary *)dictionary; 17 | + (instancetype)dictionaryWithCapacity:(NSUInteger)capacity; 18 | // Shorthand when using literal 19 | + (instancetype)d:(NSDictionary *)dictionary; 20 | 21 | - (void)setObject:(id)object forKey:(id)key; 22 | - (id)objectForKey:(id)key; 23 | 24 | - (void)removeObjectForKey:(id)key; 25 | 26 | - (NSInteger)count; 27 | 28 | - (void)setObject:(id)obj forKeyedSubscript:(id)key; 29 | - (id)objectForKeyedSubscript:(id)key; 30 | 31 | - (void)sortKeysUsingSelector:(SEL)selector deepSort:(BOOL)deepSort; 32 | - (NSArray *)allKeys; 33 | 34 | /*! 35 | Add dictionary entries. 36 | 37 | @param dictionary Dictionary, can be NSDictionary or GHODictionary 38 | */ 39 | - (void)addEntriesFromDictionary:(id)dictionary; 40 | 41 | - (NSEnumerator *)keyEnumerator; 42 | - (NSEnumerator *)reverseKeyEnumerator; 43 | 44 | - (NSDictionary *)toDictionary; 45 | 46 | - (NSArray *)map:(id (^)(id key, id value))block; 47 | - (void)enumerateKeysAndObjectsUsingBlock:(void (^)(id key, id obj, BOOL *stop))block; 48 | 49 | /*! 50 | Add object to key entry. 51 | This is to make it easier to create a dictionary of key to array values. 52 | */ 53 | - (void)addObject:(id)object forKey:(id)key; 54 | 55 | // Deprecated; Use addEntriesFromDictionary 56 | - (void)addEntriesFromOrderedDictionary:(GHODictionary *)dictionary; 57 | 58 | @end 59 | 60 | #define GHODict(DICT) ([GHODictionary dictionaryWithDictionary:DICT]) 61 | -------------------------------------------------------------------------------- /GHODictionary/include/GHODictionary.h: -------------------------------------------------------------------------------- 1 | // 2 | // GHODictionary.h 3 | // GHODictionary 4 | // 5 | // Created by Gabriel on 5/13/15. 6 | // Copyright (c) 2015 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for GHODictionary. 12 | FOUNDATION_EXPORT double GHODictionaryVersionNumber; 13 | 14 | //! Project version string for GHODictionary. 15 | FOUNDATION_EXPORT const unsigned char GHODictionaryVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | #import "GHODict.h" 20 | -------------------------------------------------------------------------------- /GHODictionaryTests/GHODictionaryTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // GHODictionaryTests.m 3 | // GHODictionaryTests 4 | // 5 | // Created by Gabriel on 5/13/15. 6 | // Copyright (c) 2015 Gabriel Handford. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @import GHODictionary; 13 | 14 | @interface GHODictionaryTests : XCTestCase 15 | @end 16 | 17 | @implementation GHODictionaryTests 18 | 19 | - (void)testDict { 20 | GHODictionary *dict = [GHODictionary dictionary]; 21 | NSMutableArray *keys = [NSMutableArray array]; 22 | for (NSInteger i = 0; i < 1024; i++) { 23 | [keys addObject:@(i)]; 24 | dict[@(i)] = @(i); 25 | } 26 | 27 | NSMutableArray *keysIterated = [NSMutableArray array]; 28 | for (id key in dict) { 29 | [keysIterated addObject:key]; 30 | } 31 | 32 | XCTAssertEqualObjects(keysIterated, keys); 33 | 34 | GHODictionary *dictCopy = [dict copy]; 35 | dictCopy[@(1)] = @"test"; 36 | 37 | NSLog(@"dictCopy=%@", dictCopy); 38 | } 39 | 40 | - (void)testDescription { 41 | GHODictionary *dict = [GHODictionary dictionaryWithDictionary:@{@"a": @(1)}]; 42 | XCTAssertEqual([dict count], 1); 43 | [dict debugDescription]; 44 | [dict description]; 45 | } 46 | 47 | - (void)testAddEntries { 48 | GHODictionary *dict = [GHODictionary dictionary]; 49 | [dict addEntriesFromDictionary:@{@"dup": @(1)}]; 50 | [dict addEntriesFromDictionary:@{@"ok": @(0)}]; 51 | [dict addEntriesFromDictionary:@{@"dup": @(2)}]; 52 | XCTAssertEqual([[dict allKeys] count], 2); 53 | XCTAssertEqualObjects(dict[@"dup"], @(2)); 54 | 55 | NSArray *expectedKeys = @[@"dup", @"ok"]; 56 | XCTAssertEqualObjects([dict allKeys], expectedKeys); 57 | 58 | dict[@"dup"] = nil; 59 | [dict removeObjectForKey:@"dup"]; // Make sure this no-ops 60 | 61 | [dict addEntriesFromDictionary:@{@"dup": @(3)}]; 62 | 63 | NSArray *expectedKeys2 = @[@"ok", @"dup"]; 64 | XCTAssertEqualObjects([dict allKeys], expectedKeys2); 65 | } 66 | 67 | - (void)testMap { 68 | GHODictionary *dict = [GHODictionary dictionary]; 69 | dict[@"a"] = @(1); 70 | dict[@"b"] = @(2); 71 | dict[@"c"] = @(3); 72 | 73 | NSArray *fromMap = [dict map:^id(id key, id value) { return @[key, value]; }]; 74 | NSArray *expected = @[@[@"a", @(1)],@[@"b", @(2)],@[@"c", @(3)]]; 75 | 76 | XCTAssertEqualObjects(fromMap, expected); 77 | } 78 | 79 | - (void)testSort { 80 | GHODictionary *dict = [[GHODictionary alloc] init]; 81 | dict[@"a"] = @(1); 82 | dict[@"c"] = @(2); 83 | dict[@"d"] = @(3); 84 | dict[@"b"] = @(4); 85 | dict[@"e"] = @(5); 86 | 87 | GHODictionary *subdict = [GHODictionary d:@{@"y": @(6), @"x": @(7), @"z": @(8)}]; 88 | dict[@"sub"] = subdict; 89 | 90 | NSArray *expected = @[@"a", @"b", @"c", @"d", @"e", @"sub"]; 91 | NSArray *expected2 = @[@"x", @"y", @"z"]; 92 | NSLog(@"Dict: %@", dict); 93 | 94 | XCTAssertNotEqualObjects(expected, [dict allKeys]); 95 | [dict sortKeysUsingSelector:@selector(localizedCaseInsensitiveCompare:) deepSort:YES]; 96 | XCTAssertEqualObjects(expected, [dict allKeys]); 97 | XCTAssertEqualObjects(expected, [[dict keyEnumerator] allObjects]); 98 | XCTAssertEqualObjects(expected2, [dict[@"sub"] allKeys]); 99 | } 100 | 101 | @end 102 | 103 | -------------------------------------------------------------------------------- /GHODictionaryTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | me.rel.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Gabriel Handford 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 all 13 | 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 THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.3 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "GHODictionary", 8 | platforms: [ 9 | .iOS(.v8), .tvOS(.v10), .macOS(.v10_10) 10 | ], 11 | products: [ 12 | .library( 13 | name: "GHODictionary", 14 | targets: ["GHODictionary"]), 15 | ], 16 | dependencies: [], 17 | targets: [ 18 | .target( 19 | name: "GHODictionary", 20 | dependencies: [], 21 | path: "GHODictionary", 22 | exclude: ["Info.plist"], 23 | cSettings: [ 24 | .headerSearchPath("include") 25 | ]), 26 | .testTarget( 27 | name: "GHODictionaryTests", 28 | dependencies: ["GHODictionary"], 29 | path: "GHODictionaryTests", 30 | exclude: ["Info.plist"]), 31 | ] 32 | ) 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | GHODictionary 2 | =========== 3 | 4 | Ordered dictionary. Enumeration occurs in the order that entries were added. If an item is overwritten, the order is unchanged. 5 | 6 | For example, 7 | 8 | ```objc 9 | #import 10 | 11 | GHODictionary *dict = [GHODictionary dictionary]; 12 | dict[@"key1"] = @(1); 13 | dict[@"key2"] = @(2); 14 | dict[@"key1"] = @(3); 15 | 16 | for (id key in dict) ... // @"key1", @"key2" 17 | 18 | [dict allKeys]; // The same as enumeration, @"key1", @"key2" 19 | 20 | [dict map:^(id key, id value) { ... }]; // (@"key1", @(3)), (@"key2", @(2)) 21 | ``` 22 | 23 | If you want to overwrite a value and have it moved to the end of the ordering, then remove it and re-add: 24 | 25 | ```objc 26 | dict[@"key1"] = nil; 27 | dict[@"key1"] = @(3); 28 | [dict allKeys]; // @"key2", @"key1" 29 | ``` 30 | 31 | Because it is ordered, it is also sortable: 32 | 33 | ```objc 34 | dict[@"b"] = @(2); 35 | dict[@"c"] = @(3); 36 | dict[@"a"] = @(1); 37 | [dict sortKeysUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; 38 | 39 | [dict allKeys]; // @"a", @"b", @"c" 40 | ``` 41 | 42 | # Swift Package Manager 43 | 44 | ```swift 45 | .package(url: "https://github.com/gabriel/GHODictionary", from: "1.2.0"), 46 | ``` 47 | 48 | # Podfile 49 | 50 | ``` 51 | pod "GHODictionary" 52 | ``` 53 | 54 | # Cartfile 55 | 56 | ``` 57 | github "gabriel/GHODictionary" 58 | ``` 59 | --------------------------------------------------------------------------------