Compare commits

...

173 Commits

Author SHA1 Message Date
Lukas Kubanek 56bfdfc953 Bumped version to 2.2.0
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-04-04 12:26:30 +02:00
Lukas Kubanek 34efc031a4 Moved safe extension API flag back to target level
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-04-04 12:20:01 +02:00
Lukas Kubanek 3541842cd3 Enabled safe extension API flag on project level
This refines #50 and applies the change to the macOS target as well.

Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-04-04 12:18:26 +02:00
Lukas Kubanek d75fe1429b Merge pull request #50 from graphiclife/master
Issue #10: Safe for app extensions
2019-04-04 12:14:34 +02:00
Måns Siljehav f8d5a75dd5 Issue #10: Safe for app extensions
• Checked the "Require Only App-Extension-Safe API" box in the Build Settings for the OrderedDictionary-iOS target.
2019-04-04 11:15:44 +02:00
Lukas Kubanek 596a7d2c1b Changed handling of modifiers in extensions
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-03-25 08:26:41 +01:00
Lukas Kubanek f2a320bc6b Initial migration to Xcode 10.2
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-03-24 15:17:52 +01:00
Lukas Kubanek f36353d61f 2018 → 2019
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-01-11 20:21:01 +01:00
Lukas Kubanek fb30ee0cc3 Fixed a reference link
Signed-off-by: Lukas Kubanek <lukas.kubanek@me.com>
2019-01-08 18:14:34 +01:00
Lukas Kubanek 4234d43565 Merge pull request #48 from gl2748/patch-1
Update package.swift
2018-10-02 22:59:51 +02:00
Iain Maitland 77d0b4937a Update package.swift
Per:
`swiftLanguageVersions` needs to be an `Int`
*Per*
https://github.com/apple/swift-package-manager/blob/master/Documentation/PackageDescriptionV4.md#package
and
https://github.com/apple/swift-package-manager/blob/master/Documentation/PackageDescriptionV4.md#swiftlanguageversions

This is causing a failing CI test for me.
2018-10-01 14:50:54 -04:00
Lukas Kubanek 4c89d79979 Bumped version to 2.1.0 2018-07-10 15:15:50 +02:00
Lukas Kubanek 397e3e4c20 Minor tweaks to the README 2018-07-10 15:11:26 +02:00
Lukas Kubanek a4abc2ee8b Updated README
- Add installation note for SPM
- Add note about no support for CocoaPods
2018-07-10 15:09:53 +02:00
Lukas Kubanek 2e54a9935b Improved #if macro 2018-07-10 14:26:35 +02:00
Lukas Kubanek ea47632047 One more refactoring of tests 2018-07-10 14:23:43 +02:00
Lukas Kubanek 1d9696939a Added initial support for SPM
Closes #42
2018-07-10 13:19:31 +02:00
Lukas Kubanek 1a26252cf7 Annotated sort methods with throws keyword 2018-07-10 13:01:31 +02:00
Lukas Kubanek 0d73c529f2 Added methods for popping/removing first and last key-value pairs
Thanks to @maicki for initial ideas

Closes #33
2018-07-10 12:53:07 +02:00
Lukas Kubanek 42030fb42a Reordered sections in OrderedDictionary 2018-07-10 12:33:29 +02:00
Lukas Kubanek e689725b4d Bumped year in license file 2018-07-10 11:57:37 +02:00
Lukas Kubanek b896bb0751 Removed empty header file 2018-07-10 11:55:38 +02:00
Lukas Kubanek 37bfcd67b2 Wrapped long method declarations 2018-07-10 11:53:52 +02:00
Lukas Kubanek cb7638e658 Added test for creation from a Dictionary
Closes #39
2018-07-10 11:53:52 +02:00
Lukas Kubanek 95e5cc9c11 Refactored tests 2018-07-10 11:53:37 +02:00
Lukas Kubanek 917cb33775 Introduced Dictionary.sorted(by:)
Refs #39
2018-07-10 11:53:37 +02:00
Lukas Kubanek 0b061bb25d Merge pull request #47 from maicki/maicki/improve-lookup
Improve key lookup
2018-07-10 11:26:54 +02:00
Michael Schneider 1d439a86ed Improve key lookup 2018-07-09 09:44:56 -07:00
Lukas Kubanek be3d9f1c69 Updated to Swift 4.2 & Xcode 10 2018-06-06 10:00:23 +02:00
Lukas Kubanek f89f30b9d1 Update README.md 2018-05-22 16:03:28 +02:00
Lukas Kubanek 9821943fff Bumped version to 2.0.0 2018-05-22 15:56:34 +02:00
Lukas Kubanek d609a252f8 Minor update 2018-05-22 15:54:09 +02:00
Lukas Kubanek 642d7e34f4 Merge pull request #40 from lukaskubanek/swift-4.1
Support for Swift 4.1
2018-05-22 15:52:55 +02:00
Lukas Kubanek 9faf5ab0ea Updated Travis config (2) 2018-03-27 20:56:06 +02:00
Lukas Kubanek f1a207a3e6 Updated Travis config 2018-03-27 20:43:51 +02:00
Lukas Kubanek aeac204817 Handled some warnings 2018-03-27 20:38:48 +02:00
Lukas Kubanek 32ef58d871 Added conditional Codable conformace for Swift 4.1
Initially, I tried to unify the implementation between the Swift 4.0 and Swift 4.1 version but had not much success…
2018-03-27 20:34:54 +02:00
Lukas Kubanek 6ee0ceaa48 Used equality in tests 2018-03-27 17:53:35 +02:00
Lukas Kubanek 0b6c95022e OrderedDictionary now truly conforms to Equatable 2018-03-27 17:38:55 +02:00
Lukas Kubanek b733108558 Introduced custom subtypes for keys and values collections 2018-03-27 17:32:46 +02:00
Lukas Kubanek 14cb718fe2 Simplified OrderedDictionarySlice type 2018-03-27 17:22:05 +02:00
Lukas Kubanek 77dbbf1c1f Updated to Xcode 9.3 β4 2018-03-27 17:21:34 +02:00
Lukas Kubanek 4be64d3c09 Updated README to mention Swift 4.1 support 2018-03-27 16:15:24 +02:00
Lukas Kubanek 2699924867 Updated version in release badge 2018-03-27 16:11:48 +02:00
Lukas Kubanek 87b46f36e1 Bumped version to 1.1.0 and updated copyright year 2018-03-27 15:34:19 +02:00
Lukas Kubanek 28cd25d536 Added support for moving elements to new index 2018-01-23 15:43:56 +01:00
Lukas Kubanek 122814a5cd Added an initializer from unsorted dictionary
Closes #30
2018-01-17 13:23:51 +01:00
Lukas Kubanek b49641a892 Improved methods for insertion checks
- Introduced canInsert(at:)
- Introduced canInsert(key:)
- Deprecated canInsert(_:)
2018-01-17 11:51:32 +01:00
Lukas Kubanek f8630257e6 Fixed a typo 2017-12-01 09:23:51 +01:00
Lukas Kubanek 46d4c52934 Updated to Xcode 9.1 beta 2 2017-10-17 18:19:28 +02:00
Lukas Kubanek fb66d1e9d8 Updated README 2017-09-25 10:59:00 +02:00
Lukas Kubanek 638d4ae0d1 Merge pull request #37 from callo90/master
Disabled Code coverage issue Carthage/Carthage#2056
2017-09-25 10:55:38 +02:00
callo90 f3d18a63fa Disabled Code coverage issue Carthage/Carthage#2056 2017-09-20 18:14:18 -05:00
Lukas Kubanek d01a024ae7 Updated README 2017-08-29 15:27:47 +02:00
Lukas Kubanek a9a37b7978 Updated README 2017-08-29 15:27:16 +02:00
Lukas Kubanek d87cac83e5 Fixed version number 2017-08-29 11:31:25 +02:00
Lukas Kubanek 754d4096da Updated license 2017-08-29 11:22:39 +02:00
Lukas Kubanek c5d09d3bc0 Updated README 2017-08-14 17:04:30 +02:00
Lukas Kubanek 5877a0a683 Exposed an unorderedDictionary property
Closes #34
2017-08-12 17:18:46 +02:00
Lukas Kubanek 5b6c8e3541 Added initializers from value sequences 2017-08-12 17:11:24 +02:00
Lukas Kubanek 502a9e128e Removed migrations code 2017-08-12 16:51:21 +02:00
Lukas Kubanek be22dfd473 Merge pull request #32 from lukaskubanek/codable
Codable Conformance
2017-08-12 16:49:46 +02:00
Lukas Kubanek a027b5c88b Added the Codable extension to iOS target 2017-08-12 16:46:26 +02:00
Lukas Kubanek 5f71a748f5 Added tests for Codable conformance 2017-08-12 16:39:44 +02:00
Lukas Kubanek 220b435d2a Moved conformance to Codable to another file 2017-08-12 16:31:25 +02:00
Lukas Kubanek 1120534fde Reduced the width of documentation comments 2017-07-18 17:24:23 +02:00
Lukas Kubanek 3dfa4db66a Added experimental conformance to Codable 2017-07-18 17:21:16 +02:00
Lukas Kubanek 3fe91a8722 Merge pull request #31 from lukaskubanek/xcode-9
Xcode 9 & Swift 4 support
2017-07-18 16:11:09 +02:00
Lukas Kubanek efb886e6c9 Further updates to Swift 4 2017-06-06 17:25:15 +02:00
Lukas Kubanek a0b52c1d28 Updated playground 2017-06-06 17:22:41 +02:00
Lukas Kubanek ccb19e2f1d Updated README 2017-06-06 17:18:14 +02:00
Lukas Kubanek 7d2362fe63 Updated Travis to use Xcode 9 in the future 2017-06-06 17:15:15 +02:00
Lukas Kubanek 117efdb7bd Initial migration to Xcode 9 and Swift 4 2017-06-06 17:13:33 +02:00
Lukas Kubanek d84ddf7f40 Updated for Xcode 8.3 beta 2017-03-18 16:01:28 +01:00
Lukas Kubanek 73ee947220 Set release number in badge manually 2017-01-12 22:43:07 +01:00
Lukas Kubanek 9715568f02 Merge pull request #23 from lukaskubanek/swift-3
Support for Swift 3
2017-01-12 22:35:20 +01:00
Lukas Kubanek 751bbe1bcc Updated playground 2017-01-12 21:01:32 +01:00
Lukas Kubanek af87ceac65 Updated tests 2017-01-12 21:00:29 +01:00
Lukas Kubanek 99f26c7f93 Removed OrderedDictionaryError thrown for invalid index updates 2017-01-12 20:57:54 +01:00
Lukas Kubanek 8e43c679de Added code comments 2017-01-12 20:05:39 +01:00
Lukas Kubanek b18549782d Made the link to code relative 2017-01-12 19:44:27 +01:00
Lukas Kubanek 5b4de32ee2 Changed the links format in README 2017-01-12 19:42:10 +01:00
Lukas Kubanek 64924a208c Updated README 2017-01-12 19:38:42 +01:00
Lukas Kubanek 310c182dc3 Minor changes 2017-01-08 12:03:53 +01:00
Lukas Kubanek c7ac65504d [Travis] Trying to get the playground validation work 2017-01-07 21:06:55 +01:00
Lukas Kubanek ce50489b8f [Travis] Fixed path to the playground validation script #3 2017-01-07 21:02:31 +01:00
Lukas Kubanek b6d563a3cc Minor changes 2017-01-07 21:01:27 +01:00
Lukas Kubanek bb3ee42176 [Travis] Fixed path to the playground validation script #2 2017-01-07 20:59:33 +01:00
Lukas Kubanek b0251e74d3 [Travis] Fixed path to the playground validation script 2017-01-07 20:54:50 +01:00
Lukas Kubanek c8d61b939b [Travis] Added initial support for validating the playground 2017-01-07 20:50:39 +01:00
Lukas Kubanek b832b9925c Made the playground compile again 2017-01-07 20:37:04 +01:00
Lukas Kubanek 21b9930d36 The standard initializer now works on arbitrary sequences 2017-01-07 19:57:27 +01:00
Lukas Kubanek f81ab4e6a0 [Travis] Removed playground validation 2017-01-07 17:25:57 +01:00
Lukas Kubanek f53a24821a [Travis] Updated the build script to work with Xcode project instead of workspace 2017-01-07 17:20:49 +01:00
Lukas Kubanek a742de8c3d [Travis] Used Xcode project instead of workspace 2017-01-07 17:17:10 +01:00
Lukas Kubanek 855e6f6a0f Updated Travis configuration
And added a script from ReactiveSwift
2017-01-07 17:13:08 +01:00
Lukas Kubanek 6cd117b224 Renamed product names in schemes 2017-01-07 16:53:21 +01:00
Lukas Kubanek dd71f6e196 Unified width of documentation comments 2017-01-07 16:52:43 +01:00
Lukas Kubanek a63943c0ae Removed the setter of the index-based subscript
This is now possible since we removed the conformance to MutableCollection.
2017-01-07 16:52:43 +01:00
Lukas Kubanek 3d78836dcd Removed conformance to MutableCollection
This enables the removal of the range subscript setter which might bring the ordered dictionary into an inconsistant state.
2017-01-07 16:52:43 +01:00
Lukas Kubanek be180eeaf4 Fixed OrderedDictionarySlice and added test for access 2017-01-07 16:52:43 +01:00
Lukas Kubanek 8a2127d8f4 Extracted and refactored description creation 2017-01-07 16:52:43 +01:00
Lukas Kubanek 616815b08c Reworked index-based insertion and update methods 2017-01-07 16:52:43 +01:00
Lukas Kubanek 90c35cb532 Introduced OrderedDictionaryError 2017-01-07 16:52:43 +01:00
Lukas Kubanek b892a31bd9 Enabled test coverage 2017-01-07 16:52:43 +01:00
Lukas Kubanek 699727683d Removed conformance to RandomAccessCollection
Because the RandomAccessCollection breaks the itegrity of the ordered dictionary by setting elements with same keys at multiple indices, OrderedDictionary cannot conform to it. The sorting methods had to be reimplemented using the method which calculates the array of sorted elements.
2017-01-07 16:52:11 +01:00
Lukas Kubanek 8efd15b99a Refactoring 2017-01-07 16:51:36 +01:00
Lukas Kubanek a043a863a7 Ordered keys and values are returned as lazy collections 2017-01-07 16:51:36 +01:00
Lukas Kubanek ccdb7bf482 Further polishing of API for Swift 3 2017-01-07 16:51:04 +01:00
Lukas Kubanek c5a5e91d2f Continuing polishing API for Swift 3 2017-01-07 16:49:37 +01:00
Lukas Kubanek b53a974021 Began polishing API for Swift 3 2017-01-07 16:48:20 +01:00
Lukas Kubanek 066b38d0ec Refactored tests and added a few new ones 2017-01-06 23:55:54 +01:00
Lukas Kubanek 8b9d033d7d Added conformance to RandomAccessCollection
This way we gain support for accessing the collection by the index and further functionality like sorting for free.
2017-01-06 23:33:44 +01:00
Lukas Kubanek befb924574 Recreated the Xcode project 2017-01-06 20:15:47 +01:00
Lukas Kubanek e9fa5e8191 Made the main module compile again 2017-01-06 19:29:11 +01:00
Lukas Kubanek fa8cb4d120 Run automatic migration to Swift 3 2017-01-06 17:30:59 +01:00
Lukas Kubanek d7daeb0518 Merge pull request #19 from lukaskubanek/swift2.3
Swift 2.3
2016-09-24 21:19:47 +02:00
Lukas Kubanek 9b6c798a17 Migrated the iOS target to Swift 2.3 as well 2016-09-24 21:12:31 +02:00
Lukas Kubanek 959f4f0eb1 Updated Travis configuration 2016-09-24 21:07:53 +02:00
Lukas Kubanek 040aadd65f Updated the README 2016-09-24 21:06:01 +02:00
Lukas Kubanek b6a99e3ffe Changed the target name to use “Mac” suffix instead of “OSX”
Closes #15
2016-09-24 21:00:10 +02:00
Lukas Kubanek 20d4d7e7c4 Ran the migrator for Swift 2.3 2016-09-23 18:44:18 +02:00
Lukas Kubanek a8a69e4570 Updated schemes for new test target product names 2016-06-16 12:02:37 +02:00
Lukas Kubanek cea6cb0952 Updated test target product names 2016-06-16 10:22:36 +02:00
Lukas Kubanek fae6eb2617 Reordered groups 2016-06-15 18:33:39 +02:00
Lukas Kubanek 0e3030af48 Reverted the empty initializer 2016-05-05 18:50:23 +02:00
Lukas Kubanek 9a255de350 Improved the playground 2016-05-05 18:43:27 +02:00
Lukas Kubanek ca1fc87240 Updated LICENSE and added reference to chagelog 2016-05-05 17:49:03 +02:00
Lukas Kubanek dff7877e06 Updated README 2016-05-05 17:41:28 +02:00
Lukas Kubanek 32ec1a11ce Cleanup 2016-05-05 16:56:15 +02:00
Lukas Kubanek 4d8f31303a Used default generator
Refs #3
2016-05-05 15:17:13 +02:00
Lukas Kubanek b4da0afe8b Introduced method valueForKey(_:)
Refs #13
2016-05-05 14:44:44 +02:00
Lukas Kubanek 34e3aa1c95 Refactored tests 2016-05-05 14:19:44 +02:00
Lukas Kubanek 0ec1461200 Added conformance to DictionaryLiteralConvertible and improved description output
Closes #4
Refs #11
2016-05-05 13:16:50 +02:00
Lukas Kubanek 3706b45822 Updated project settings to work with extensions
Refs #10
2016-04-14 20:07:38 +02:00
Lukas Kubanek 2438623b7c Updated README for 0.6 release 2016-03-27 16:55:29 +02:00
Lukas Kubanek af69193370 Updated README 2016-03-27 16:34:25 +02:00
Lukas Kubanek 20c169a7b8 Updated Travis CI configuration for Xcode 7.3 2016-03-27 16:21:25 +02:00
Lukas Kubanek 87efd44e09 Minor refactoring 2016-03-27 13:17:41 +02:00
Lukas Kubanek e7bba55479 Updated syntax for Swift 2.2 2016-02-16 07:46:01 +01:00
Lukas Kubanek 4dcdf588ee Updated to Xcode 7.3 beta 2016-01-24 11:23:56 +01:00
Lukas Kubanek 4065061d25 Bumped version 2016-01-06 23:51:04 +01:00
Marius Bergmann 60ffb98742 Set iOS deployment target to 8.0
All tests also pass on 8.0. This makes it possible to use the project in
an 8.x application.
2016-01-05 16:56:09 +01:00
Lukas Kubanek d70db906df Fix in the README 2015-12-18 10:19:39 +01:00
Lukas Kubanek 30bb351de2 Updated to Xcode 7.2 2015-12-15 12:20:05 +01:00
Lukas Kubanek 0022833380 Fixed a typo 2015-12-10 10:11:04 +01:00
Lukas Kubanek 1219d6dd8a Updated README and playground 2015-12-06 14:48:50 +01:00
Lukas Kubanek c5e6b63a9c Added support for sorting
Closes #5
2015-12-06 14:30:23 +01:00
Lukas Kubanek a2d0ef2c1b Cleaned up tests 2015-12-06 14:16:42 +01:00
Lukas Kubanek 61729a772b Updated framework search headers 2015-12-06 13:56:39 +01:00
Lukas Kubanek 5e51f91e07 The backing store properties are now initialized in-place 2015-12-04 13:58:55 +01:00
Lukas Kubanek 5acd33d10a Removed the dependency on Nimble for tests 2015-11-27 15:13:04 +01:00
Lukas Kubanek 1a4623ceff And hopefully the last change 2015-11-15 18:45:01 +01:00
Lukas Kubanek 8016abd95b Synxed with an older version of synx and fixed Carthage 2015-11-15 17:52:18 +01:00
Lukas Kubanek e58469f8e4 Synxed the project structure and updated dependencies
- Added Carthage to .gitignore
- Updated Nimble to v3.0
- Added a script for updating the dependencies
2015-11-15 17:01:36 +01:00
Lukas Kubanek 100e077a0d Added a convenience method for inserting new element 2015-11-04 13:51:17 +01:00
Lukas Kubanek 72ccef23af Updated installation section in README 2015-10-21 11:50:19 +02:00
Lukas Kubanek 1a9ac85931 Added properties orderedKeys & orderedValues
Closes #1
2015-10-14 20:48:41 +02:00
Lukas Kubanek 9074b8abe8 Updated readme 2015-09-11 10:24:58 +02:00
Lukas Kubanek 7f58e9ae8d Minor refactoring 2015-09-11 10:23:01 +02:00
Lukas Kubanek feffcd9041 Improved fatal error message for insertion using negative index 2015-09-11 10:22:53 +02:00
Lukas Kubanek e963b30ff8 Added support for index-based insertion 2015-09-11 10:17:28 +02:00
Lukas Kubanek 23725866ab Improved fatal error messages 2015-09-11 09:35:42 +02:00
Lukas Kubanek 9aa12bb2aa Updated readme 2015-09-10 21:58:39 +02:00
Lukas Kubanek 4bcf559767 Updated the Swift/Xcode requirement 2015-09-10 19:16:48 +02:00
Lukas Kubanek c318c55cab Added support for == operator and initialization from pairs 2015-09-10 19:10:39 +02:00
Lukas Kubanek b00cb645f5 Ignored own builds 2015-09-10 19:10:13 +02:00
Lukas Kubanek c2bfb83d40 Typo 2015-08-30 18:02:26 +02:00
Lukas Kubanek 9c2c3f0c21 Added method containsKey(:) 2015-08-30 12:50:52 +02:00
Lukas Kubanek e8240aef93 Added Travis badge 2015-08-30 11:53:28 +02:00
Lukas Kubanek 049f05acae Put Nimble builds into the repository 2015-08-30 11:45:57 +02:00
Lukas Kubanek 7ad09edbc0 Added Travis CI configuration 2015-08-30 11:37:04 +02:00
Lukas Kubanek 39f90292f6 Typo 2015-08-30 11:21:30 +02:00
23 changed files with 2037 additions and 653 deletions
+3
View File
@@ -27,3 +27,6 @@ DerivedData
# Carthage
Carthage
# SPM
.build
+49
View File
@@ -0,0 +1,49 @@
# Git
branches:
only:
- master
# OS
os: osx
language: objective-c
# Xcode Project
xcode_project: OrderedDictionary.xcodeproj
# Build Matrix
matrix:
include:
# Swift 4.0 / macOS
- osx_image: xcode9.2
xcode_scheme: OrderedDictionary-Mac
env:
- XCODE_SDK=macosx
- XCODE_ACTION="build test"
- XCODE_DESTINATION="arch=x86_64"
- XCODE_PLAYGROUND_TARGET="x86_64-apple-macosx10.10"
# Swift 4.0 / iOS
- osx_image: xcode9.2
xcode_scheme: OrderedDictionary-iOS
env:
- XCODE_SDK=iphonesimulator
- XCODE_ACTION="build-for-testing test-without-building"
- XCODE_DESTINATION="platform=iOS Simulator,name=iPhone 6s,OS=10.1"
# Swift 4.1 / macOS
- osx_image: xcode9.3beta
xcode_scheme: OrderedDictionary-Mac
env:
- XCODE_SDK=macosx
- XCODE_ACTION="build test"
- XCODE_DESTINATION="arch=x86_64"
- XCODE_PLAYGROUND_TARGET="x86_64-apple-macosx10.10"
# Swift 4.1 / iOS
- osx_image: xcode9.3beta
xcode_scheme: OrderedDictionary-iOS
env:
- XCODE_SDK=iphonesimulator
- XCODE_ACTION="build-for-testing test-without-building"
- XCODE_DESTINATION="platform=iOS Simulator,name=iPhone 6s,OS=10.1"
# Build Script
script:
- Scripts/build.sh
-1
View File
@@ -1 +0,0 @@
github "Quick/Nimble" "e84623d953d811f74a2afcda4fa0c8121e7dad7d"
-1
View File
@@ -1 +0,0 @@
github "Quick/Nimble" "e84623d953d811f74a2afcda4fa0c8121e7dad7d"
+1 -1
View File
@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2015 Lukas Kubanek
Copyright (c) 2015-2019 Lukas Kubanek
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+252 -251
View File
@@ -7,260 +7,224 @@
objects = {
/* Begin PBXBuildFile section */
803F9CD51B92324C002F728F /* OrderedDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = 803F9CD21B92324C002F728F /* OrderedDictionary.h */; settings = {ATTRIBUTES = (Public, ); }; };
803F9CD81B9232EE002F728F /* OrderedDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 803F9CD71B9232EE002F728F /* OrderedDictionary.swift */; settings = {ASSET_TAGS = (); }; };
803F9CF41B925B1C002F728F /* OrderedDictionary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 803F9CC61B923207002F728F /* OrderedDictionary.framework */; settings = {ASSET_TAGS = (); }; };
803F9CFD1B925B4C002F728F /* OrderedDictionaryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 803F9CFC1B925B4C002F728F /* OrderedDictionaryTests.swift */; settings = {ASSET_TAGS = (); }; };
803F9D001B925BBF002F728F /* Nimble.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 803F9CE91B925AE5002F728F /* Nimble.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
803F9D011B925BE9002F728F /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 803F9CE91B925AE5002F728F /* Nimble.framework */; };
8060976B1B92F2D200DB20CF /* OrderedDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 803F9CD71B9232EE002F728F /* OrderedDictionary.swift */; };
8060976C1B92F2D900DB20CF /* OrderedDictionary.h in Headers */ = {isa = PBXBuildFile; fileRef = 803F9CD21B92324C002F728F /* OrderedDictionary.h */; settings = {ATTRIBUTES = (Public, ); }; };
806097761B92F44F00DB20CF /* OrderedDictionary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 806097631B92F20400DB20CF /* OrderedDictionary.framework */; settings = {ASSET_TAGS = (); }; };
8060977C1B92F4A000DB20CF /* OrderedDictionaryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 803F9CFC1B925B4C002F728F /* OrderedDictionaryTests.swift */; };
806097801B92F4F000DB20CF /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8060977F1B92F4F000DB20CF /* Nimble.framework */; settings = {ASSET_TAGS = (); }; };
806097821B92F4FC00DB20CF /* Nimble.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8060977F1B92F4F000DB20CF /* Nimble.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
8055B0421E201C5D009DC3EE /* OrderedDictionary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8055B0381E201C5D009DC3EE /* OrderedDictionary.framework */; };
8055B0591E201DF3009DC3EE /* OrderedDictionaryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8055B0581E201DF3009DC3EE /* OrderedDictionaryTests.swift */; };
80A203A11F3F483700622481 /* OrderedDictionary+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80A203A01F3F483700622481 /* OrderedDictionary+Codable.swift */; };
80A203A21F3F4C1F00622481 /* OrderedDictionary+Codable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80A203A01F3F483700622481 /* OrderedDictionary+Codable.swift */; };
80B28EA01E201EC9007E3A77 /* OrderedDictionary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 80B28E971E201EC8007E3A77 /* OrderedDictionary.framework */; };
80B28EB01E201F1C007E3A77 /* OrderedDictionaryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8055B0581E201DF3009DC3EE /* OrderedDictionaryTests.swift */; };
80E8E21D1E20301E00395E49 /* OrderedDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80E8E21C1E20301E00395E49 /* OrderedDictionary.swift */; };
80E8E21F1E20425B00395E49 /* OrderedDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80E8E21C1E20301E00395E49 /* OrderedDictionary.swift */; };
80E8E2301E2133D100395E49 /* OrderedDictionary+Description.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80E8E22F1E2133D100395E49 /* OrderedDictionary+Description.swift */; };
80E8E2311E2133D100395E49 /* OrderedDictionary+Description.swift in Sources */ = {isa = PBXBuildFile; fileRef = 80E8E22F1E2133D100395E49 /* OrderedDictionary+Description.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
803F9CF51B925B1C002F728F /* PBXContainerItemProxy */ = {
8055B0431E201C5D009DC3EE /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 803F9CBD1B923207002F728F /* Project object */;
containerPortal = 8055B02F1E201C5D009DC3EE /* Project object */;
proxyType = 1;
remoteGlobalIDString = 803F9CC51B923207002F728F;
remoteGlobalIDString = 8055B0371E201C5D009DC3EE;
remoteInfo = OrderedDictionary;
};
806097771B92F44F00DB20CF /* PBXContainerItemProxy */ = {
80B28EA11E201EC9007E3A77 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 803F9CBD1B923207002F728F /* Project object */;
containerPortal = 8055B02F1E201C5D009DC3EE /* Project object */;
proxyType = 1;
remoteGlobalIDString = 806097621B92F20400DB20CF;
remoteGlobalIDString = 80B28E961E201EC8007E3A77;
remoteInfo = "OrderedDictionary-iOS";
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
803F9CFF1B925BA2002F728F /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
803F9D001B925BBF002F728F /* Nimble.framework in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 0;
};
806097811B92F4F500DB20CF /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
806097821B92F4FC00DB20CF /* Nimble.framework in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
803F9CC61B923207002F728F /* OrderedDictionary.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OrderedDictionary.framework; sourceTree = BUILT_PRODUCTS_DIR; };
803F9CD21B92324C002F728F /* OrderedDictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OrderedDictionary.h; sourceTree = "<group>"; };
803F9CD41B92324C002F728F /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
803F9CD71B9232EE002F728F /* OrderedDictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrderedDictionary.swift; sourceTree = "<group>"; };
803F9CE91B925AE5002F728F /* Nimble.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Nimble.framework; path = Carthage/Build/Mac/Nimble.framework; sourceTree = "<group>"; };
803F9CEF1B925B1C002F728F /* OrderedDictionary-OSX-Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "OrderedDictionary-OSX-Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
803F9CFC1B925B4C002F728F /* OrderedDictionaryTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrderedDictionaryTests.swift; sourceTree = "<group>"; };
803F9CFE1B925B56002F728F /* Info-Tests.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "Info-Tests.plist"; path = "Supporting Files/Info-Tests.plist"; sourceTree = SOURCE_ROOT; };
806097631B92F20400DB20CF /* OrderedDictionary.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OrderedDictionary.framework; sourceTree = BUILT_PRODUCTS_DIR; };
806097711B92F44F00DB20CF /* OrderedDictionary-iOS-Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "OrderedDictionary-iOS-Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
8060977F1B92F4F000DB20CF /* Nimble.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Nimble.framework; path = Carthage/Build/iOS/Nimble.framework; sourceTree = "<group>"; };
80F94F181B926A60000A96E7 /* OrderedDictionary.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = OrderedDictionary.playground; sourceTree = "<group>"; };
804879371E217C7700AD31A3 /* build.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = build.sh; sourceTree = "<group>"; };
804879381E217CA100AD31A3 /* validate-playgrounds.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "validate-playgrounds.sh"; sourceTree = "<group>"; };
8055B0381E201C5D009DC3EE /* OrderedDictionary.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OrderedDictionary.framework; sourceTree = BUILT_PRODUCTS_DIR; };
8055B0411E201C5D009DC3EE /* OrderedDictionary_Mac_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OrderedDictionary_Mac_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
8055B0581E201DF3009DC3EE /* OrderedDictionaryTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrderedDictionaryTests.swift; sourceTree = "<group>"; };
807AA68F1F1E587A00576474 /* OrderedDictionary+Codable.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "OrderedDictionary+Codable.playground"; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
80A203A01F3F483700622481 /* OrderedDictionary+Codable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "OrderedDictionary+Codable.swift"; sourceTree = "<group>"; };
80B28E971E201EC8007E3A77 /* OrderedDictionary.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OrderedDictionary.framework; sourceTree = BUILT_PRODUCTS_DIR; };
80B28E9F1E201EC9007E3A77 /* OrderedDictionary_iOS_Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OrderedDictionary_iOS_Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
80B28EB41E201F81007E3A77 /* Info-Tests.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-Tests.plist"; sourceTree = "<group>"; };
80B28EB51E201F81007E3A77 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
80B28EB71E2020DD007E3A77 /* OrderedDictionary.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = OrderedDictionary.playground; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
80DE329220F4CAFA0053EDA7 /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = "<group>"; };
80DE329320F4DD910053EDA7 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
80DE329420F4DD910053EDA7 /* LICENSE.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = LICENSE.md; sourceTree = "<group>"; };
80E8E21C1E20301E00395E49 /* OrderedDictionary.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OrderedDictionary.swift; sourceTree = "<group>"; };
80E8E22F1E2133D100395E49 /* OrderedDictionary+Description.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "OrderedDictionary+Description.swift"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
803F9CC21B923207002F728F /* Frameworks */ = {
8055B0341E201C5D009DC3EE /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
803F9CEC1B925B1C002F728F /* Frameworks */ = {
8055B03E1E201C5D009DC3EE /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
803F9CF41B925B1C002F728F /* OrderedDictionary.framework in Frameworks */,
803F9D011B925BE9002F728F /* Nimble.framework in Frameworks */,
8055B0421E201C5D009DC3EE /* OrderedDictionary.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
8060975F1B92F20400DB20CF /* Frameworks */ = {
80B28E931E201EC8007E3A77 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
8060976E1B92F44F00DB20CF /* Frameworks */ = {
80B28E9C1E201EC9007E3A77 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
806097761B92F44F00DB20CF /* OrderedDictionary.framework in Frameworks */,
806097801B92F4F000DB20CF /* Nimble.framework in Frameworks */,
80B28EA01E201EC9007E3A77 /* OrderedDictionary.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
803F9CBC1B923207002F728F = {
804879361E217C7700AD31A3 /* Scripts */ = {
isa = PBXGroup;
children = (
803F9CD11B92324C002F728F /* Sources */,
80F94F171B926A60000A96E7 /* Playgrounds */,
803F9CFB1B925B4C002F728F /* Tests */,
803F9CD31B92324C002F728F /* Supporting Files */,
803F9CE81B9259F3002F728F /* Frameworks */,
803F9CC71B923207002F728F /* Products */,
804879371E217C7700AD31A3 /* build.sh */,
804879381E217CA100AD31A3 /* validate-playgrounds.sh */,
);
path = Scripts;
sourceTree = "<group>";
};
8055B02E1E201C5D009DC3EE = {
isa = PBXGroup;
children = (
80DE329320F4DD910053EDA7 /* README.md */,
80DE329420F4DD910053EDA7 /* LICENSE.md */,
80DE329220F4CAFA0053EDA7 /* Package.swift */,
8055B0521E201D24009DC3EE /* Sources */,
80B28EB11E201F72007E3A77 /* Playgrounds */,
8055B0571E201DF3009DC3EE /* Tests */,
80B28EB31E201F81007E3A77 /* Supporting Files */,
804879361E217C7700AD31A3 /* Scripts */,
8055B0391E201C5D009DC3EE /* Products */,
);
sourceTree = "<group>";
};
803F9CC71B923207002F728F /* Products */ = {
8055B0391E201C5D009DC3EE /* Products */ = {
isa = PBXGroup;
children = (
803F9CC61B923207002F728F /* OrderedDictionary.framework */,
803F9CEF1B925B1C002F728F /* OrderedDictionary-OSX-Tests.xctest */,
806097631B92F20400DB20CF /* OrderedDictionary.framework */,
806097711B92F44F00DB20CF /* OrderedDictionary-iOS-Tests.xctest */,
8055B0381E201C5D009DC3EE /* OrderedDictionary.framework */,
8055B0411E201C5D009DC3EE /* OrderedDictionary_Mac_Tests.xctest */,
80B28E971E201EC8007E3A77 /* OrderedDictionary.framework */,
80B28E9F1E201EC9007E3A77 /* OrderedDictionary_iOS_Tests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
803F9CD11B92324C002F728F /* Sources */ = {
8055B0521E201D24009DC3EE /* Sources */ = {
isa = PBXGroup;
children = (
803F9CD21B92324C002F728F /* OrderedDictionary.h */,
803F9CD71B9232EE002F728F /* OrderedDictionary.swift */,
80E8E21C1E20301E00395E49 /* OrderedDictionary.swift */,
80A203A01F3F483700622481 /* OrderedDictionary+Codable.swift */,
80E8E22F1E2133D100395E49 /* OrderedDictionary+Description.swift */,
);
path = Sources;
sourceTree = "<group>";
};
803F9CD31B92324C002F728F /* Supporting Files */ = {
8055B0571E201DF3009DC3EE /* Tests */ = {
isa = PBXGroup;
children = (
803F9CD41B92324C002F728F /* Info.plist */,
803F9CFE1B925B56002F728F /* Info-Tests.plist */,
);
path = "Supporting Files";
sourceTree = "<group>";
};
803F9CE81B9259F3002F728F /* Frameworks */ = {
isa = PBXGroup;
children = (
8060977D1B92F4D900DB20CF /* OSX */,
8060977E1B92F4DF00DB20CF /* iOS */,
);
name = Frameworks;
sourceTree = "<group>";
};
803F9CFB1B925B4C002F728F /* Tests */ = {
isa = PBXGroup;
children = (
803F9CFC1B925B4C002F728F /* OrderedDictionaryTests.swift */,
8055B0581E201DF3009DC3EE /* OrderedDictionaryTests.swift */,
);
path = Tests;
sourceTree = "<group>";
};
8060977D1B92F4D900DB20CF /* OSX */ = {
80B28EB11E201F72007E3A77 /* Playgrounds */ = {
isa = PBXGroup;
children = (
803F9CE91B925AE5002F728F /* Nimble.framework */,
);
name = OSX;
sourceTree = "<group>";
};
8060977E1B92F4DF00DB20CF /* iOS */ = {
isa = PBXGroup;
children = (
8060977F1B92F4F000DB20CF /* Nimble.framework */,
);
name = iOS;
sourceTree = "<group>";
};
80F94F171B926A60000A96E7 /* Playgrounds */ = {
isa = PBXGroup;
children = (
80F94F181B926A60000A96E7 /* OrderedDictionary.playground */,
80B28EB71E2020DD007E3A77 /* OrderedDictionary.playground */,
807AA68F1F1E587A00576474 /* OrderedDictionary+Codable.playground */,
);
path = Playgrounds;
sourceTree = "<group>";
};
80B28EB31E201F81007E3A77 /* Supporting Files */ = {
isa = PBXGroup;
children = (
80B28EB51E201F81007E3A77 /* Info.plist */,
80B28EB41E201F81007E3A77 /* Info-Tests.plist */,
);
path = "Supporting Files";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
803F9CC31B923207002F728F /* Headers */ = {
8055B0351E201C5D009DC3EE /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
803F9CD51B92324C002F728F /* OrderedDictionary.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
806097601B92F20400DB20CF /* Headers */ = {
80B28E941E201EC8007E3A77 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
8060976C1B92F2D900DB20CF /* OrderedDictionary.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
803F9CC51B923207002F728F /* OrderedDictionary-OSX */ = {
8055B0371E201C5D009DC3EE /* OrderedDictionary-Mac */ = {
isa = PBXNativeTarget;
buildConfigurationList = 803F9CCE1B923207002F728F /* Build configuration list for PBXNativeTarget "OrderedDictionary-OSX" */;
buildConfigurationList = 8055B04C1E201C5D009DC3EE /* Build configuration list for PBXNativeTarget "OrderedDictionary-Mac" */;
buildPhases = (
803F9CC11B923207002F728F /* Sources */,
803F9CC21B923207002F728F /* Frameworks */,
803F9CC31B923207002F728F /* Headers */,
803F9CC41B923207002F728F /* Resources */,
8055B0331E201C5D009DC3EE /* Sources */,
8055B0341E201C5D009DC3EE /* Frameworks */,
8055B0351E201C5D009DC3EE /* Headers */,
8055B0361E201C5D009DC3EE /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = "OrderedDictionary-OSX";
name = "OrderedDictionary-Mac";
productName = OrderedDictionary;
productReference = 803F9CC61B923207002F728F /* OrderedDictionary.framework */;
productReference = 8055B0381E201C5D009DC3EE /* OrderedDictionary.framework */;
productType = "com.apple.product-type.framework";
};
803F9CEE1B925B1C002F728F /* OrderedDictionary-OSX-Tests */ = {
8055B0401E201C5D009DC3EE /* OrderedDictionary-Mac-Tests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 803F9CF71B925B1C002F728F /* Build configuration list for PBXNativeTarget "OrderedDictionary-OSX-Tests" */;
buildConfigurationList = 8055B04F1E201C5D009DC3EE /* Build configuration list for PBXNativeTarget "OrderedDictionary-Mac-Tests" */;
buildPhases = (
803F9CEB1B925B1C002F728F /* Sources */,
803F9CEC1B925B1C002F728F /* Frameworks */,
803F9CED1B925B1C002F728F /* Resources */,
803F9CFF1B925BA2002F728F /* CopyFiles */,
8055B03D1E201C5D009DC3EE /* Sources */,
8055B03E1E201C5D009DC3EE /* Frameworks */,
8055B03F1E201C5D009DC3EE /* Resources */,
);
buildRules = (
);
dependencies = (
803F9CF61B925B1C002F728F /* PBXTargetDependency */,
8055B0441E201C5D009DC3EE /* PBXTargetDependency */,
);
name = "OrderedDictionary-OSX-Tests";
name = "OrderedDictionary-Mac-Tests";
productName = OrderedDictionaryTests;
productReference = 803F9CEF1B925B1C002F728F /* OrderedDictionary-OSX-Tests.xctest */;
productReference = 8055B0411E201C5D009DC3EE /* OrderedDictionary_Mac_Tests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
806097621B92F20400DB20CF /* OrderedDictionary-iOS */ = {
80B28E961E201EC8007E3A77 /* OrderedDictionary-iOS */ = {
isa = PBXNativeTarget;
buildConfigurationList = 806097681B92F20400DB20CF /* Build configuration list for PBXNativeTarget "OrderedDictionary-iOS" */;
buildConfigurationList = 80B28EA81E201EC9007E3A77 /* Build configuration list for PBXNativeTarget "OrderedDictionary-iOS" */;
buildPhases = (
8060975E1B92F20400DB20CF /* Sources */,
8060975F1B92F20400DB20CF /* Frameworks */,
806097601B92F20400DB20CF /* Headers */,
806097611B92F20400DB20CF /* Resources */,
80B28E921E201EC8007E3A77 /* Sources */,
80B28E931E201EC8007E3A77 /* Frameworks */,
80B28E941E201EC8007E3A77 /* Headers */,
80B28E951E201EC8007E3A77 /* Resources */,
);
buildRules = (
);
@@ -268,95 +232,103 @@
);
name = "OrderedDictionary-iOS";
productName = "OrderedDictionary-iOS";
productReference = 806097631B92F20400DB20CF /* OrderedDictionary.framework */;
productReference = 80B28E971E201EC8007E3A77 /* OrderedDictionary.framework */;
productType = "com.apple.product-type.framework";
};
806097701B92F44F00DB20CF /* OrderedDictionary-iOS-Tests */ = {
80B28E9E1E201EC9007E3A77 /* OrderedDictionary-iOS-Tests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 806097791B92F44F00DB20CF /* Build configuration list for PBXNativeTarget "OrderedDictionary-iOS-Tests" */;
buildConfigurationList = 80B28EAB1E201EC9007E3A77 /* Build configuration list for PBXNativeTarget "OrderedDictionary-iOS-Tests" */;
buildPhases = (
8060976D1B92F44F00DB20CF /* Sources */,
8060976E1B92F44F00DB20CF /* Frameworks */,
8060976F1B92F44F00DB20CF /* Resources */,
806097811B92F4F500DB20CF /* CopyFiles */,
80B28E9B1E201EC9007E3A77 /* Sources */,
80B28E9C1E201EC9007E3A77 /* Frameworks */,
80B28E9D1E201EC9007E3A77 /* Resources */,
);
buildRules = (
);
dependencies = (
806097781B92F44F00DB20CF /* PBXTargetDependency */,
80B28EA21E201EC9007E3A77 /* PBXTargetDependency */,
);
name = "OrderedDictionary-iOS-Tests";
productName = "OrderedDictionary-iOS-Tests";
productReference = 806097711B92F44F00DB20CF /* OrderedDictionary-iOS-Tests.xctest */;
productName = "OrderedDictionary-iOSTests";
productReference = 80B28E9F1E201EC9007E3A77 /* OrderedDictionary_iOS_Tests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
803F9CBD1B923207002F728F /* Project object */ = {
8055B02F1E201C5D009DC3EE /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0700;
LastUpgradeCheck = 0700;
LastSwiftUpdateCheck = 0820;
LastUpgradeCheck = 1020;
ORGANIZATIONNAME = "Lukas Kubanek";
TargetAttributes = {
803F9CC51B923207002F728F = {
CreatedOnToolsVersion = 7.0;
8055B0371E201C5D009DC3EE = {
CreatedOnToolsVersion = 8.2.1;
LastSwiftMigration = 1020;
ProvisioningStyle = Automatic;
};
803F9CEE1B925B1C002F728F = {
CreatedOnToolsVersion = 7.0;
8055B0401E201C5D009DC3EE = {
CreatedOnToolsVersion = 8.2.1;
LastSwiftMigration = 1020;
ProvisioningStyle = Automatic;
};
806097621B92F20400DB20CF = {
CreatedOnToolsVersion = 7.0;
80B28E961E201EC8007E3A77 = {
CreatedOnToolsVersion = 8.2.1;
LastSwiftMigration = 1020;
ProvisioningStyle = Automatic;
};
806097701B92F44F00DB20CF = {
CreatedOnToolsVersion = 7.0;
80B28E9E1E201EC9007E3A77 = {
CreatedOnToolsVersion = 8.2.1;
LastSwiftMigration = 1020;
ProvisioningStyle = Automatic;
};
};
};
buildConfigurationList = 803F9CC01B923207002F728F /* Build configuration list for PBXProject "OrderedDictionary" */;
buildConfigurationList = 8055B0321E201C5D009DC3EE /* Build configuration list for PBXProject "OrderedDictionary" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 803F9CBC1B923207002F728F;
productRefGroup = 803F9CC71B923207002F728F /* Products */;
mainGroup = 8055B02E1E201C5D009DC3EE;
productRefGroup = 8055B0391E201C5D009DC3EE /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
803F9CC51B923207002F728F /* OrderedDictionary-OSX */,
803F9CEE1B925B1C002F728F /* OrderedDictionary-OSX-Tests */,
806097621B92F20400DB20CF /* OrderedDictionary-iOS */,
806097701B92F44F00DB20CF /* OrderedDictionary-iOS-Tests */,
8055B0371E201C5D009DC3EE /* OrderedDictionary-Mac */,
8055B0401E201C5D009DC3EE /* OrderedDictionary-Mac-Tests */,
80B28E961E201EC8007E3A77 /* OrderedDictionary-iOS */,
80B28E9E1E201EC9007E3A77 /* OrderedDictionary-iOS-Tests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
803F9CC41B923207002F728F /* Resources */ = {
8055B0361E201C5D009DC3EE /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
803F9CED1B925B1C002F728F /* Resources */ = {
8055B03F1E201C5D009DC3EE /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
806097611B92F20400DB20CF /* Resources */ = {
80B28E951E201EC8007E3A77 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
8060976F1B92F44F00DB20CF /* Resources */ = {
80B28E9D1E201EC9007E3A77 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
@@ -366,71 +338,89 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
803F9CC11B923207002F728F /* Sources */ = {
8055B0331E201C5D009DC3EE /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
803F9CD81B9232EE002F728F /* OrderedDictionary.swift in Sources */,
80E8E2301E2133D100395E49 /* OrderedDictionary+Description.swift in Sources */,
80E8E21D1E20301E00395E49 /* OrderedDictionary.swift in Sources */,
80A203A11F3F483700622481 /* OrderedDictionary+Codable.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
803F9CEB1B925B1C002F728F /* Sources */ = {
8055B03D1E201C5D009DC3EE /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
803F9CFD1B925B4C002F728F /* OrderedDictionaryTests.swift in Sources */,
8055B0591E201DF3009DC3EE /* OrderedDictionaryTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
8060975E1B92F20400DB20CF /* Sources */ = {
80B28E921E201EC8007E3A77 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
8060976B1B92F2D200DB20CF /* OrderedDictionary.swift in Sources */,
80E8E2311E2133D100395E49 /* OrderedDictionary+Description.swift in Sources */,
80E8E21F1E20425B00395E49 /* OrderedDictionary.swift in Sources */,
80A203A21F3F4C1F00622481 /* OrderedDictionary+Codable.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
8060976D1B92F44F00DB20CF /* Sources */ = {
80B28E9B1E201EC9007E3A77 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
8060977C1B92F4A000DB20CF /* OrderedDictionaryTests.swift in Sources */,
80B28EB01E201F1C007E3A77 /* OrderedDictionaryTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
803F9CF61B925B1C002F728F /* PBXTargetDependency */ = {
8055B0441E201C5D009DC3EE /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 803F9CC51B923207002F728F /* OrderedDictionary-OSX */;
targetProxy = 803F9CF51B925B1C002F728F /* PBXContainerItemProxy */;
target = 8055B0371E201C5D009DC3EE /* OrderedDictionary-Mac */;
targetProxy = 8055B0431E201C5D009DC3EE /* PBXContainerItemProxy */;
};
806097781B92F44F00DB20CF /* PBXTargetDependency */ = {
80B28EA21E201EC9007E3A77 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 806097621B92F20400DB20CF /* OrderedDictionary-iOS */;
targetProxy = 806097771B92F44F00DB20CF /* PBXContainerItemProxy */;
target = 80B28E961E201EC8007E3A77 /* OrderedDictionary-iOS */;
targetProxy = 80B28EA11E201EC9007E3A77 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
803F9CCC1B923207002F728F /* Debug */ = {
8055B04A1E201C5D009DC3EE /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
@@ -450,33 +440,51 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.0;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
803F9CCD1B923207002F728F /* Release */ = {
8055B04B1E201C5D009DC3EE /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "-";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
@@ -490,27 +498,29 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
MACOSX_DEPLOYMENT_TARGET = 10.10;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_SWIFT3_OBJC_INFERENCE = Default;
SWIFT_VERSION = 4.0;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
803F9CCF1B923207002F728F /* Debug */ = {
8055B04D1E201C5D009DC3EE /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
APPLICATION_EXTENSION_API_ONLY = YES;
CLANG_ENABLE_CODE_COVERAGE = NO;
CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/Mac",
);
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = "Supporting Files/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
@@ -518,23 +528,20 @@
PRODUCT_BUNDLE_IDENTIFIER = com.lukaskubanek.OrderedDictionary;
PRODUCT_NAME = OrderedDictionary;
SKIP_INSTALL = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
803F9CD01B923207002F728F /* Release */ = {
8055B04E1E201C5D009DC3EE /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
APPLICATION_EXTENSION_API_ONLY = YES;
CLANG_ENABLE_CODE_COVERAGE = NO;
CODE_SIGN_IDENTITY = "";
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/Mac",
);
FRAMEWORK_VERSION = A;
INFOPLIST_FILE = "Supporting Files/Info.plist";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
@@ -545,40 +552,37 @@
};
name = Release;
};
803F9CF81B925B1C002F728F /* Debug */ = {
8055B0501E201C5D009DC3EE /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/Mac",
);
INFOPLIST_FILE = "Supporting Files/Info-Tests.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.lukaskubanek.OrderedDictionaryTests;
PRODUCT_NAME = "$(TARGET_NAME)";
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
};
name = Debug;
};
803F9CF91B925B1C002F728F /* Release */ = {
8055B0511E201C5D009DC3EE /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/Mac",
);
INFOPLIST_FILE = "Supporting Files/Info-Tests.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.lukaskubanek.OrderedDictionaryTests;
PRODUCT_NAME = "$(TARGET_NAME)";
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
};
name = Release;
};
806097691B92F20400DB20CF /* Debug */ = {
80B28EA91E201EC9007E3A77 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
APPLICATION_EXTENSION_API_ONLY = YES;
CLANG_ENABLE_CODE_COVERAGE = NO;
CODE_SIGN_IDENTITY = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
@@ -594,10 +598,13 @@
};
name = Debug;
};
8060976A1B92F20400DB20CF /* Release */ = {
80B28EAA1E201EC9007E3A77 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
APPLICATION_EXTENSION_API_ONLY = YES;
CLANG_ENABLE_CODE_COVERAGE = NO;
CODE_SIGN_IDENTITY = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
@@ -614,34 +621,26 @@
};
name = Release;
};
8060977A1B92F44F00DB20CF /* Debug */ = {
80B28EAC1E201EC9007E3A77 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/iOS",
);
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
INFOPLIST_FILE = "Supporting Files/Info-Tests.plist";
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.lukaskubanek.OrderedDictionary-iOS-Tests";
PRODUCT_NAME = "$(TARGET_NAME)";
PRODUCT_BUNDLE_IDENTIFIER = "com.lukaskubanek.OrderedDictionary-iOSTests";
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SDKROOT = iphoneos;
};
name = Debug;
};
8060977B1B92F44F00DB20CF /* Release */ = {
80B28EAD1E201EC9007E3A77 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/iOS",
);
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
INFOPLIST_FILE = "Supporting Files/Info-Tests.plist";
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "com.lukaskubanek.OrderedDictionary-iOS-Tests";
PRODUCT_NAME = "$(TARGET_NAME)";
PRODUCT_BUNDLE_IDENTIFIER = "com.lukaskubanek.OrderedDictionary-iOSTests";
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
@@ -650,50 +649,52 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
803F9CC01B923207002F728F /* Build configuration list for PBXProject "OrderedDictionary" */ = {
8055B0321E201C5D009DC3EE /* Build configuration list for PBXProject "OrderedDictionary" */ = {
isa = XCConfigurationList;
buildConfigurations = (
803F9CCC1B923207002F728F /* Debug */,
803F9CCD1B923207002F728F /* Release */,
8055B04A1E201C5D009DC3EE /* Debug */,
8055B04B1E201C5D009DC3EE /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
803F9CCE1B923207002F728F /* Build configuration list for PBXNativeTarget "OrderedDictionary-OSX" */ = {
8055B04C1E201C5D009DC3EE /* Build configuration list for PBXNativeTarget "OrderedDictionary-Mac" */ = {
isa = XCConfigurationList;
buildConfigurations = (
803F9CCF1B923207002F728F /* Debug */,
803F9CD01B923207002F728F /* Release */,
8055B04D1E201C5D009DC3EE /* Debug */,
8055B04E1E201C5D009DC3EE /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
803F9CF71B925B1C002F728F /* Build configuration list for PBXNativeTarget "OrderedDictionary-OSX-Tests" */ = {
8055B04F1E201C5D009DC3EE /* Build configuration list for PBXNativeTarget "OrderedDictionary-Mac-Tests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
803F9CF81B925B1C002F728F /* Debug */,
803F9CF91B925B1C002F728F /* Release */,
8055B0501E201C5D009DC3EE /* Debug */,
8055B0511E201C5D009DC3EE /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
806097681B92F20400DB20CF /* Build configuration list for PBXNativeTarget "OrderedDictionary-iOS" */ = {
80B28EA81E201EC9007E3A77 /* Build configuration list for PBXNativeTarget "OrderedDictionary-iOS" */ = {
isa = XCConfigurationList;
buildConfigurations = (
806097691B92F20400DB20CF /* Debug */,
8060976A1B92F20400DB20CF /* Release */,
80B28EA91E201EC9007E3A77 /* Debug */,
80B28EAA1E201EC9007E3A77 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
806097791B92F44F00DB20CF /* Build configuration list for PBXNativeTarget "OrderedDictionary-iOS-Tests" */ = {
80B28EAB1E201EC9007E3A77 /* Build configuration list for PBXNativeTarget "OrderedDictionary-iOS-Tests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
8060977A1B92F44F00DB20CF /* Debug */,
8060977B1B92F44F00DB20CF /* Release */,
80B28EAC1E201EC9007E3A77 /* Debug */,
80B28EAD1E201EC9007E3A77 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 803F9CBD1B923207002F728F /* Project object */;
rootObject = 8055B02F1E201C5D009DC3EE /* Project object */;
}
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0700"
LastUpgradeVersion = "1020"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -14,9 +14,9 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "803F9CC51B923207002F728F"
BlueprintIdentifier = "8055B0371E201C5D009DC3EE"
BuildableName = "OrderedDictionary.framework"
BlueprintName = "OrderedDictionary-OSX"
BlueprintName = "OrderedDictionary-Mac"
ReferencedContainer = "container:OrderedDictionary.xcodeproj">
</BuildableReference>
</BuildActionEntry>
@@ -26,16 +26,15 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
codeCoverageEnabled = "YES">
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "803F9CEE1B925B1C002F728F"
BuildableName = "OrderedDictionary-OSX-Tests.xctest"
BlueprintName = "OrderedDictionary-OSX-Tests"
BlueprintIdentifier = "8055B0401E201C5D009DC3EE"
BuildableName = "OrderedDictionary_Mac_Tests.xctest"
BlueprintName = "OrderedDictionary-Mac-Tests"
ReferencedContainer = "container:OrderedDictionary.xcodeproj">
</BuildableReference>
</TestableReference>
@@ -43,9 +42,9 @@
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "803F9CC51B923207002F728F"
BlueprintIdentifier = "8055B0371E201C5D009DC3EE"
BuildableName = "OrderedDictionary.framework"
BlueprintName = "OrderedDictionary-OSX"
BlueprintName = "OrderedDictionary-Mac"
ReferencedContainer = "container:OrderedDictionary.xcodeproj">
</BuildableReference>
</MacroExpansion>
@@ -65,9 +64,9 @@
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "803F9CC51B923207002F728F"
BlueprintIdentifier = "8055B0371E201C5D009DC3EE"
BuildableName = "OrderedDictionary.framework"
BlueprintName = "OrderedDictionary-OSX"
BlueprintName = "OrderedDictionary-Mac"
ReferencedContainer = "container:OrderedDictionary.xcodeproj">
</BuildableReference>
</MacroExpansion>
@@ -83,9 +82,9 @@
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "803F9CC51B923207002F728F"
BlueprintIdentifier = "8055B0371E201C5D009DC3EE"
BuildableName = "OrderedDictionary.framework"
BlueprintName = "OrderedDictionary-OSX"
BlueprintName = "OrderedDictionary-Mac"
ReferencedContainer = "container:OrderedDictionary.xcodeproj">
</BuildableReference>
</MacroExpansion>
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0700"
LastUpgradeVersion = "1020"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -14,7 +14,7 @@
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "806097621B92F20400DB20CF"
BlueprintIdentifier = "80B28E961E201EC8007E3A77"
BuildableName = "OrderedDictionary.framework"
BlueprintName = "OrderedDictionary-iOS"
ReferencedContainer = "container:OrderedDictionary.xcodeproj">
@@ -26,15 +26,14 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
codeCoverageEnabled = "YES">
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "806097701B92F44F00DB20CF"
BuildableName = "OrderedDictionary-iOS-Tests.xctest"
BlueprintIdentifier = "80B28E9E1E201EC9007E3A77"
BuildableName = "OrderedDictionary_iOS_Tests.xctest"
BlueprintName = "OrderedDictionary-iOS-Tests"
ReferencedContainer = "container:OrderedDictionary.xcodeproj">
</BuildableReference>
@@ -43,7 +42,7 @@
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "806097621B92F20400DB20CF"
BlueprintIdentifier = "80B28E961E201EC8007E3A77"
BuildableName = "OrderedDictionary.framework"
BlueprintName = "OrderedDictionary-iOS"
ReferencedContainer = "container:OrderedDictionary.xcodeproj">
@@ -65,7 +64,7 @@
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "806097621B92F20400DB20CF"
BlueprintIdentifier = "80B28E961E201EC8007E3A77"
BuildableName = "OrderedDictionary.framework"
BlueprintName = "OrderedDictionary-iOS"
ReferencedContainer = "container:OrderedDictionary.xcodeproj">
@@ -83,7 +82,7 @@
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "806097621B92F20400DB20CF"
BlueprintIdentifier = "80B28E961E201EC8007E3A77"
BuildableName = "OrderedDictionary.framework"
BlueprintName = "OrderedDictionary-iOS"
ReferencedContainer = "container:OrderedDictionary.xcodeproj">
+27
View File
@@ -0,0 +1,27 @@
// swift-tools-version:4.2
import PackageDescription
let package = Package(
name: "OrderedDictionary",
products: [
.library(
name: "OrderedDictionary",
targets: ["OrderedDictionary"]
)
],
dependencies: [],
targets: [
.target(
name: "OrderedDictionary",
dependencies: [],
path: "Sources"
),
.testTarget(
name: "OrderedDictionaryTests",
dependencies: ["OrderedDictionary"],
path: "Tests"
)
],
swiftLanguageVersions: [4]
)
@@ -0,0 +1,49 @@
import Foundation
import OrderedDictionary
let orderedDictionary1: OrderedDictionary<String, Int> = [
"A": 42,
"B": 100,
"C": 11
]
// ======================================================= //
// MARK: - JSON Encoding & Decoding
// ======================================================= //
let jsonEncoder = JSONEncoder()
let jsonData = try! jsonEncoder.encode(orderedDictionary1)
let jsonString = String(data: jsonData, encoding: .utf8)
let jsonDecoder = JSONDecoder()
let orderedDictionary2 = try! jsonDecoder.decode(OrderedDictionary<String, Int>.self, from: jsonData)
orderedDictionary1 == orderedDictionary2
// ======================================================= //
// MARK: - Property List Encoding & Decoding
// ======================================================= //
let plistEncoder = PropertyListEncoder()
let plistData = try! plistEncoder.encode(orderedDictionary1)
let plistDecoder = PropertyListDecoder()
let orderedDictionary3 = try! plistDecoder.decode(OrderedDictionary<String, Int>.self, from: plistData)
orderedDictionary1 == orderedDictionary3
// ======================================================= //
// MARK: - Non-codable Type
// ======================================================= //
struct NonCodableType {
var string: String
}
let orderedDictionary4: OrderedDictionary<String, NonCodableType> = [
"A" : NonCodableType(string: "Foo"),
"B" : NonCodableType(string: "Bar"),
"C" : NonCodableType(string: "Baz")
]
//try? jsonEncoder.encode(x)
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='5.0' target-platform='macos'>
<timeline fileName='timeline.xctimeline'/>
</playground>
@@ -1,65 +1,134 @@
import OrderedDictionary
////
// Initialize an ordered dictionary using an array of key-value pairs
////
// ======================================================= //
// Helpers
// ======================================================= //
var orderedDictionary: OrderedDictionary<String, Int> = [
("A", 1),
("B", 2),
("C", 3),
("D", 4)
]
print(orderedDictionary) // => [A: 1, B: 2, C: 3, D: 4]
////
// Loop through the contents
////
for (index, (key, value)) in orderedDictionary.enumerate() {
print("\(index): (\(key): \(value))")
func print(_ optional: Any?) {
print(optional as Any)
}
// => 0: (A: 1)
// => 1: (B: 2)
// => 2: (C: 3)
// => 3: (D: 4)
// ======================================================= //
// Construction
// ======================================================= //
////
// Modify the values by setting the value for key
////
// Construct an ordered dictionary using a dictionary literal
var orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3, "D": 4]
// Output the ordered dictionary
print(orderedDictionary) // => [A: 1, B: 2, C: 3, D: 4]
// ======================================================= //
// Enumeration
// ======================================================= //
// Loop through the ordered dictionary
for (key, value) in orderedDictionary {
print("[\(key): \(value)]") // => [A: 1], => [B: 2], => [C: 3], => [D: 4]
}
// Loop through the ordered dictionary with an additional index
for (index, element) in orderedDictionary.enumerated() {
print("(\(index): [\(element.key): \(element.value)])") // => (0: [A: 1]), => (1: [B: 2]), => (2: [C: 3]), => (3: [D: 4])
}
// ======================================================= //
// Acessing Content
// ======================================================= //
// Access the value for an existing key using the subscript
print(orderedDictionary["A"]) // => Optional(1)
// Access the value for a non-existent key using the subscript
print(orderedDictionary["X"]) // => nil
// Access the value for a key using the method
print(orderedDictionary.value(forKey: "A")) // => Optional(1)
// Access the value for a non-existent key using the method
print(orderedDictionary.value(forKey: "X")) // => nil
// Access the key-value pair (element) at an existing index
print(orderedDictionary[2]) // => ("C", 3)
// Access the key-value pair (element) at a non-existent index
//print(orderedDictionary[10]) // => fatal error
// Get the index for an existing key
print(orderedDictionary.index(forKey: "D")) // => Optional(3)
// ======================================================= //
// Modifying Content Using Keys
// ======================================================= //
// Modify the value for an existing key using the subscript
orderedDictionary["A"] = 100
orderedDictionary["E"] = 5
orderedDictionary["B"] = nil
orderedDictionary.updateValue(42, forKey: "D")
print(orderedDictionary["A"]) // => Optional(100)
// Modify the value for an existing key using the method
orderedDictionary.updateValue(42, forKey: "D")
print(orderedDictionary["D"]) // => Optional(42)
// Append a new key-value pair by setting a value for an non-existent key
orderedDictionary["E"] = 5
print(orderedDictionary) // => [A: 100, B: 2, C: 3, D: 42, E: 5]
// Remove a key-value pair by setting `nil` value for an existing key
orderedDictionary["B"] = nil
print(orderedDictionary["B"]) // => nil
print(orderedDictionary) // => [A: 100, C: 3, D: 42, E: 5]
print(orderedDictionary["A"]) // => Optional(100)
print(orderedDictionary["B"]) // => nil
print(orderedDictionary["C"]) // => Optional(3)
print(orderedDictionary["D"]) // => Optional(42)
print(orderedDictionary["E"]) // => Optional(5)
// ======================================================= //
// Modifying Content Using Indexes
// ======================================================= //
////
// Modify the values by setting the element for index
////
// Modify an element at an existing index
let replacedElement = orderedDictionary.update(("F", 235), at: 2)
print(orderedDictionary[2]) // => ("F", 235)
print(orderedDictionary) // => [A: 100, C: 3, F: 235, E: 5]
print(replacedElement) // => Optional("D", 42)
orderedDictionary[2] = ("F", 235)
orderedDictionary.updateElement(("K", 12), atIndex: 1)
orderedDictionary.removeAtIndex(0)
// Modify an element at a non-existent index
//orderedDictionary.update(("L", 0), at: 100) // => fatal error
print(orderedDictionary) // => [K: 12, F: 235, E: 5]
// ======================================================= //
// Sorting
// ======================================================= //
print(orderedDictionary[0]) // => ("K", 12)
print(orderedDictionary[1]) // => ("F", 235)
print(orderedDictionary[2]) // => ("E", 5)
// print(orderedDictionary[3]) // => fatal error
// Sort the ordered dictionary using a closure
orderedDictionary.sort {
if $0.value == $1.value {
return $0.key < $1.key
} else {
return $0.value < $1.value
}
}
print(orderedDictionary.indexForKey("K")) // => Optional(0)
print(orderedDictionary.indexForKey("F")) // => Optional(1)
print(orderedDictionary.indexForKey("E")) // => Optional(2)
print(orderedDictionary.indexForKey("A")) // => nil
print(orderedDictionary.indexForKey("C")) // => nil
print(orderedDictionary) // => [C: 3, E: 5, A: 100, F: 235]
// ======================================================= //
// Removing Content
// ======================================================= //
// Remove value for an existing key
let removedValue = orderedDictionary.removeValue(forKey: "F")
print(removedValue) // => Optional(235)
print(orderedDictionary["F"]) // => nil
print(orderedDictionary) // => [C: 3, E: 5, A: 100]
// Remove value for a non-existent key
orderedDictionary.removeValue(forKey: "X")
print(orderedDictionary) // => [C: 3, E: 5, A: 100]
// Remove element at an existing index
let removedElement = orderedDictionary.remove(at: 1)
print(removedElement) // => Optional((E, 5))
print(orderedDictionary) // => [C: 3, A: 100]
// Remove element at a non-existent index
orderedDictionary.remove(at: 42)
print(orderedDictionary) // => [C: 3, A: 100]
// Remove all elements
orderedDictionary.removeAll()
print(orderedDictionary) // => [:]
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='5.0' target-platform='osx' requires-full-environment='true'>
<playground version='5.0' target-platform='osx'>
<timeline fileName='timeline.xctimeline'/>
</playground>
+40 -96
View File
@@ -1,120 +1,64 @@
# OrderedDictionary
[![][image-1]][1] [![][image-2]][2] ![][image-3] [![][image-4]][3] [![][image-5]][4]
[![](https://img.shields.io/travis/lukaskubanek/OrderedDictionary.svg?style=flat-square "Build")](https://travis-ci.org/lukaskubanek/OrderedDictionary) [![](https://img.shields.io/badge/release-v2.2.0-blue.svg?style=flat-square)](https://github.com/lukaskubanek/OrderedDictionary/releases) [![](https://img.shields.io/badge/Swift-4.0+-orange.svg?style=flat-square)](https://developer.apple.com/swift/ "Swift 4") ![](https://img.shields.io/badge/platform-macOS/iOS-yellowgreen.svg?style=flat-square "Platform: macOS/iOS") [![](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat-square "Carthage compatible")](https://github.com/Carthage/Carthage)
[![](https://img.shields.io/badge/SPM-compatible-brightgreen.svg?style=flat-square "SPM compatible")](https://github.com/Carthage/Carthage) [![](https://img.shields.io/badge/license-MIT-lightgrey.svg?style=flat-square "License: MIT")](LICENSE.md)
This is a lightweight implementation of an ordered dictionary data structure in Swift packed into a µframework.
**OrderedDictionary** is a lightweight implementation of an ordered dictionary data structure in Swift.
`OrderedDictioary` is an immutable generic collection which combines the features of `Dictionary` and `Array`. Like `Dictionary` it stores key-value pairs and maps the keys to values. Additionally these pairs are sorted by zero-based integer index like in `Array`. The `OrderedDictionary` provides similar APIs to the collections from the Swift standard library and allows accessing the content by keys or indexes.
The `OrderedDictionary` struct is a generic collection which combines the features of `Dictionary` and `Array` from the Swift standard library. Like `Dictionary` it stores key-value pairs with each key being unique and maps each key to an associated value. Like `Array` it stores those pairs sorted and accessible by a zero-based integer index.
Internally `OrderedDictionary` uses a backing store composed of an instance of `Dictionary` for storing the key-value pairs and an instance of `Array` for managing the ordered keys.
`OrderedDictionary` provides similar APIs like collections from the Swift standard library. This includes accessing contents by keys or indices, inserting and removing elements, iterating, sorting etc.
Internally, `OrderedDictionary` uses a backing store composed of an instance of `Dictionary` for storing the key-value pairs and an instance of `Array` for managing the ordered keys. This means it is not the most performant implementation possible, but it gets its job done by reusing most functionality from the Swift standard library.
## Requirements
- Swift 2.0
- Xcode 7.0 beta 6+
- iOS 8.0+ / OS X 10.10+
- Swift 4.0, 4.2, 5.0
- Xcode 9.2+
- iOS 8.0+ / macOS 10.10+
## Installation
The easiest way to integrate `OrderedDictionary` to your project is to use [Carthage][5]. Add following line to your `Cartfile`:
The library is distributed as a Swift framework and can be integrated into your project in following ways:
```
github "lukaskubanek/OrderedDictionary" ~> 0.1
#### Carthage
If you use [Carthage](https://github.com/Carthage/Carthage) for managing your dependencies, put OrderedDictionary into your `Cartfile`:
```plain
github "lukaskubanek/OrderedDictionary"
```
Then drag the `OrderedDictionary.xcodeproj` or the `OrderedDictionary.framework` into your project/workspace and link against the `OrderedDictionary.framework`.
Then, drag either the `OrderedDictionary.xcodeproj` or the `OrderedDictionary.framework` into your project/workspace and link your target against the `OrderedDictionary.framework`. Also make sure that the framework [gets copied](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application) to your application bundle.
Finally make sure the framework gets copied into your application bundle.
#### Swift Package Manager
## Example Usage
Another option is to use the [Swift Package Manager](https://swift.org/package-manager/). If you prefer this option, put OrderedDictionary as a dependency to your `Package.swift`:
```swift
import OrderedDictionary
////
// Initialize an ordered dictionary using an array of key-value pairs
////
var orderedDictionary: OrderedDictionary<String, Int> = [
("A", 1),
("B", 2),
("C", 3),
("D", 4)
]
print(orderedDictionary) // => [A: 1, B: 2, C: 3, D: 4]
////
// Loop through the contents
////
for (index, (key, value)) in orderedDictionary.enumerate() {
print("\(index): (\(key): \(value))")
}
// => 0: (A: 1)
// => 1: (B: 2)
// => 2: (C: 3)
// => 3: (D: 4)
////
// Modify the values by setting the value for key
////
orderedDictionary["A"] = 100
orderedDictionary["E"] = 5
orderedDictionary["B"] = nil
orderedDictionary.updateValue(42, forKey: "D")
print(orderedDictionary) // => [A: 100, C: 3, D: 42, E: 5]
print(orderedDictionary["A"]) // => Optional(100)
print(orderedDictionary["B"]) // => nil
print(orderedDictionary["C"]) // => Optional(3)
print(orderedDictionary["D"]) // => Optional(42)
print(orderedDictionary["E"]) // => Optional(5)
////
// Modify the values by setting the element for index
////
orderedDictionary[2] = ("F", 235)
orderedDictionary.updateElement(("K", 12), atIndex: 1)
orderedDictionary.removeAtIndex(0)
print(orderedDictionary) // => [K: 12, F: 235, E: 5]
print(orderedDictionary[0]) // => ("K", 12)
print(orderedDictionary[1]) // => ("F", 235)
print(orderedDictionary[2]) // => ("E", 5)
// print(orderedDictionary[3]) // => fatal error
print(orderedDictionary.indexForKey("K")) // => Optional(0)
print(orderedDictionary.indexForKey("F")) // => Optional(1)
print(orderedDictionary.indexForKey("E")) // => Optional(2)
print(orderedDictionary.indexForKey("A")) // => nil
print(orderedDictionary.indexForKey("C")) // => nil
```plain
.package(url: "https://github.com/lukaskubanek/OrderedDictionary.git", from: "2.2.0")
```
#### Git Submodules
Yet another option is using [Git submodules](http://git-scm.com/book/en/v2/Git-Tools-Submodules) and integrating the Xcode project `OrderedDictionary.xcodeproj` from the submodule directly to your Xcode workspace.
#### ⚠️ Note About CocoaPods
Although there is high demand for [CocoaPods](https://cocoapods.org) support, this method won't be officially supported by this library. Since I'm not using CocoaPods myself and since I think this method will be once replaced by the Swift Package Manager, I don't want to put any effort in maintaining an official podspec. If you really want to include this library via CocoaPods, there is still a way by creating a custom podspec (see the last section of [this post](https://guides.cocoapods.org/syntax/podfile.html#pod)).
## Usage & Docs
For the usage of this library please refer to [the example playground](Playgrounds/OrderedDictionary.playground/Contents.swift). For documentation please refer to [the documentation comments](Sources/OrderedDictionary.swift).
## Changelog
The changelog is managed on the [GitHub releases page](https://github.com/lukaskubanek/OrderedDictionary/releases).
## Author
Lukas Kubanek // [lukaskubanek.com][6] // [@kubanekl][7]
Lukas Kubanek // [lukaskubanek.com](http://lukaskubanek.com) // [@kubanekl](https://twitter.com/kubanekl)
## License
OrderedDictionary is release under the [MIT License][8].
[1]: https://github.com/lukaskubanek/OrderedDictionary/releases
[2]: https://developer.apple.com/swift/
[3]: https://github.com/Carthage/Carthage
[4]: LICENSE.md
[5]: https://github.com/Carthage/Carthage/
[6]: http://lukaskubanek.com
[7]: https://twitter.com/kubanekl
[8]: LICENSE.md
[image-1]: https://img.shields.io/github/release/lukaskubanek/OrderedDictionary.svg?style=flat-square
[image-2]: https://img.shields.io/badge/Swift-2.0_(7b6)-orange.svg?style=flat-square
[image-3]: https://img.shields.io/badge/Platform-OS_X%20&_iOS-yellowgreen.svg?style=flat-square
[image-4]: https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat-square "Carthage compatible"
[image-5]: https://img.shields.io/badge/license-MIT-lightgrey.svg?style=flat-square "License"
**OrderedDictionary** is provided under the [MIT License](LICENSE.md).
+54
View File
@@ -0,0 +1,54 @@
#!/bin/bash
# This script was taken from the ReactiveSwift repository.
# https://github.com/ReactiveCocoa/ReactiveSwift/blob/master/script/build
BUILD_DIRECTORY="build"
CONFIGURATION="Release"
if [[ -z $TRAVIS_XCODE_PROJECT ]]; then
echo "Error: \$TRAVIS_XCODE_PROJECT is not set."
exit 1
fi
if [[ -z $TRAVIS_XCODE_SCHEME ]]; then
echo "Error: \$TRAVIS_XCODE_SCHEME is not set."
exit 1
fi
if [[ -z $XCODE_ACTION ]]; then
echo "Error: \$XCODE_ACTION is not set."
exit 1
fi
if [[ -z $XCODE_SDK ]]; then
echo "Error: \$XCODE_SDK is not set."
exit 1
fi
if [[ -z $XCODE_DESTINATION ]]; then
echo "Error: \$XCODE_DESTINATION is not set."
exit 1
fi
set -o pipefail
xcodebuild $XCODE_ACTION \
-project "$TRAVIS_XCODE_PROJECT" \
-scheme "$TRAVIS_XCODE_SCHEME" \
-sdk "$XCODE_SDK" \
-destination "$XCODE_DESTINATION" \
-derivedDataPath "${BUILD_DIRECTORY}" \
-configuration $CONFIGURATION \
ENABLE_TESTABILITY=YES \
GCC_GENERATE_DEBUGGING_SYMBOLS=NO \
RUN_CLANG_STATIC_ANALYZER=NO | xcpretty
result=$?
if [ "$result" -ne 0 ]; then
exit $result
fi
if [[ $XCODE_SDK = "macosx" ]]; then
echo "SDK is ${XCODE_SDK}, validating playground..."
. Scripts/validate-playgrounds.sh
fi
+23
View File
@@ -0,0 +1,23 @@
#!/bin/bash
if [[ -z $BUILD_DIRECTORY ]]; then
echo "Error: \$BUILD_DIRECTORY is not set."
exit 1
fi
if [[ -z $XCODE_PLAYGROUND_TARGET ]]; then
echo "Error: \$XCODE_PLAYGROUND_TARGET is not set."
exit 1
fi
PAGES_PATH=Playgrounds/OrderedDictionary.playground/Contents.swift
swift -v -target ${XCODE_PLAYGROUND_TARGET} \
-D NOT_IN_PLAYGROUND \
-F ${BUILD_DIRECTORY}/Build/Products/${CONFIGURATION} ${PAGES_PATH} > /dev/null
result=$?
rm -Rf ${BUILD_DIRECTORY}
exit $result
+136
View File
@@ -0,0 +1,136 @@
#if swift(>=4.1)
extension OrderedDictionary: Encodable where Key: Encodable, Value: Encodable {
/// __inheritdoc__
public func encode(to encoder: Encoder) throws {
// Encode the ordered dictionary as an array of alternating key-value pairs.
var container = encoder.unkeyedContainer()
for (key, value) in self {
try container.encode(key)
try container.encode(value)
}
}
}
extension OrderedDictionary: Decodable where Key: Decodable, Value: Decodable {
/// __inheritdoc__
public init(from decoder: Decoder) throws {
// Decode the ordered dictionary from an array of alternating key-value pairs.
self.init()
var container = try decoder.unkeyedContainer()
while !container.isAtEnd {
let key = try container.decode(Key.self)
guard !container.isAtEnd else { throw DecodingError.unkeyedContainerReachedEndBeforeValue(decoder.codingPath) }
let value = try container.decode(Value.self)
self[key] = value
}
}
}
#else
extension OrderedDictionary: Encodable {
/// __inheritdoc__
public func encode(to encoder: Encoder) throws {
// Since Swift 4.0 lacks the protocol conditional conformance support, we have to make the
// whole OrderedDictionary type conform to Encodable and assert that the key and value
// types conform to Encodable. Furthermore, we leverage a trick of super encoders to be
// able to encode objects without knowing their exact types. This trick was used in the
// standard library for encoding/decoding Dictionary before Swift 4.1.
_assertTypeIsEncodable(Key.self, in: type(of: self))
_assertTypeIsEncodable(Value.self, in: type(of: self))
var container = encoder.unkeyedContainer()
for (key, value) in self {
let keyEncoder = container.superEncoder()
try (key as! Encodable).encode(to: keyEncoder)
let valueEncoder = container.superEncoder()
try (value as! Encodable).encode(to: valueEncoder)
}
}
private func _assertTypeIsEncodable<T>(_ type: T.Type, in wrappingType: Any.Type) {
guard T.self is Encodable.Type else {
if T.self == Encodable.self || T.self == Codable.self {
preconditionFailure("\(wrappingType) does not conform to Encodable because Encodable does not conform to itself. You must use a concrete type to encode or decode.")
} else {
preconditionFailure("\(wrappingType) does not conform to Encodable because \(T.self) does not conform to Encodable.")
}
}
}
}
extension OrderedDictionary: Decodable {
/// __inheritdoc__
public init(from decoder: Decoder) throws {
// Since Swift 4.0 lacks the protocol conditional conformance support, we have to make the
// whole OrderedDictionary type conform to Decodable and assert that the key and value
// types conform to Decodable. Furthermore, we leverage a trick of super decoders to be
// able to decode objects without knowing their exact types. This trick was used in the
// standard library for encoding/decoding Dictionary before Swift 4.1.
self.init()
_assertTypeIsDecodable(Key.self, in: type(of: self))
_assertTypeIsDecodable(Value.self, in: type(of: self))
var container = try decoder.unkeyedContainer()
let keyMetaType = (Key.self as! Decodable.Type)
let valueMetaType = (Value.self as! Decodable.Type)
while !container.isAtEnd {
let keyDecoder = try container.superDecoder()
let key = try keyMetaType.init(from: keyDecoder) as! Key
guard !container.isAtEnd else { throw DecodingError.unkeyedContainerReachedEndBeforeValue(decoder.codingPath) }
let valueDecoder = try container.superDecoder()
let value = try valueMetaType.init(from: valueDecoder) as! Value
self[key] = value
}
}
private func _assertTypeIsDecodable<T>(_ type: T.Type, in wrappingType: Any.Type) {
guard T.self is Decodable.Type else {
if T.self == Decodable.self || T.self == Codable.self {
preconditionFailure("\(wrappingType) does not conform to Decodable because Decodable does not conform to itself. You must use a concrete type to encode or decode.")
} else {
preconditionFailure("\(wrappingType) does not conform to Decodable because \(T.self) does not conform to Decodable.")
}
}
}
}
#endif
extension DecodingError {
fileprivate static func unkeyedContainerReachedEndBeforeValue(
_ codingPath: [CodingKey]
) -> DecodingError {
return DecodingError.dataCorrupted(
DecodingError.Context(
codingPath: codingPath,
debugDescription: "Unkeyed container reached end before value in key-value pair."
)
)
}
}
@@ -0,0 +1,50 @@
extension OrderedDictionary: CustomStringConvertible {
/// A textual representation of the ordered dictionary.
public var description: String {
return makeDescription(debug: false)
}
}
extension OrderedDictionary: CustomDebugStringConvertible {
/// A textual representation of the ordered dictionary, suitable for debugging.
public var debugDescription: String {
return makeDescription(debug: true)
}
}
extension OrderedDictionary {
fileprivate func makeDescription(debug: Bool) -> String {
// The implementation of the description is inspired by zwaldowski's implementation of the
// ordered dictionary. See https://bit.ly/2RiWfJu
if isEmpty { return "[:]" }
let printFunction: (Any, inout String) -> () = {
if debug {
return { debugPrint($0, separator: "", terminator: "", to: &$1) }
} else {
return { print($0, separator: "", terminator: "", to: &$1) }
}
}()
let descriptionForItem: (Any) -> String = { item in
var description = ""
printFunction(item, &description)
return description
}
let bodyComponents = map { element in
return descriptionForItem(element.key) + ": " + descriptionForItem(element.value)
}
let body = bodyComponents.joined(separator: ", ")
return "[\(body)]"
}
}
-10
View File
@@ -1,10 +0,0 @@
//
// OrderedDictionary.h
// OrderedDictionary
//
// Created by Lukas Kubanek on 29/08/15.
// Copyright © 2015 Lukas Kubanek. All rights reserved.
//
extern double OrderedDictionaryVersionNumber;
extern const unsigned char OrderedDictionaryVersionString[];
+631 -120
View File
@@ -1,166 +1,677 @@
//
// OrderedDictionary.swift
// OrderedDictionary
//
// Created by Lukas Kubanek on 29/08/15.
// Copyright © 2015 Lukas Kubanek. All rights reserved.
//
/// A generic collection for storing key-value pairs in an ordered manner.
///
/// Same as in a dictionary all keys in the collection are unique and have an associated value.
/// Same as in an array, all key-value pairs (elements) are kept sorted and accessible by
/// a zero-based integer index.
public struct OrderedDictionary<Key: Hashable, Value>: BidirectionalCollection {
/// The `OrderedDictionary` is a collection which combines the features of `Dictionary` and `Array`.
/// It maps keys to values and additionally sorts the key-value pairs by zero-based integer index.
public struct OrderedDictionary<Key : Hashable, Value>: CollectionType, ArrayLiteralConvertible, CustomStringConvertible {
// ======================================================= //
// MARK: - Type Aliases
// ======================================================= //
/// The type of the key-value pair stored in the ordered dictionary.
public typealias Element = (key: Key, value: Value)
/// The type of the index.
public typealias Index = Int
/// The type of the indices collection.
public typealias Indices = CountableRange<Int>
/// The type of the contiguous subrange of the ordered dictionary's elements.
///
/// - SeeAlso: OrderedDictionarySlice
public typealias SubSequence = OrderedDictionarySlice<Key, Value>
// ======================================================= //
// MARK: - Initialization
// ======================================================= //
public init() {
self.orderedKeys = []
self.keysToValues = [:]
/// Creates an empty ordered dictionary.
public init() {}
/// Creates an ordered dictionary from a sequence of values keyed by a key which gets extracted
/// from the value in the provided closure.
///
/// - Parameter values: The sequence of values.
/// - Parameter getKey: The closure which provides a key for the given value from the values
/// sequence.
public init<Values: Sequence>(
values: Values,
keyedBy getKey: (Value) -> Key
) where Values.Element == Value {
self.init(values.map { (getKey($0), $0) })
}
public init(arrayLiteral elements: Element...) {
self.init()
/// Creates an ordered dictionary from a sequence of values keyed by a key loaded from the value
/// at the given key path.
///
/// - Parameter values: The sequence of values.
/// - Parameter keyPath: The key path for the value to locate its key at.
public init(values: [Value], keyedBy keyPath: KeyPath<Value, Key>) {
self.init(values.map { ($0[keyPath: keyPath], $0) })
}
/// Creates an ordered dictionary from a regular unsorted dictionary by sorting it using the
/// the given sort function.
///
/// - Parameter unsorted: The unsorted dictionary.
/// - Parameter areInIncreasingOrder: The sort function which compares the key-value pairs.
public init(
unsorted: Dictionary<Key, Value>,
areInIncreasingOrder: (Element, Element) throws -> Bool
) rethrows {
let elements = try unsorted
.map { (key: $0.key, value: $0.value) }
.sorted(by: areInIncreasingOrder)
for element in elements {
self[element.0] = element.1
self.init(elements)
}
/// Creates an ordered dictionary from a sequence of key-value pairs.
///
/// - Parameter elements: The key-value pairs that will make up the new ordered dictionary.
/// Each key in `elements` must be unique.
public init<S: Sequence>(_ elements: S) where S.Element == Element {
for (key, value) in elements {
precondition(!containsKey(key), "Elements sequence contains duplicate keys")
self[key] = value
}
}
// MARK: - Type Aliases
// ======================================================= //
// MARK: - Ordered Keys & Values
// ======================================================= //
public typealias Element = (Key, Value)
public typealias Index = Int
/// A collection containing just the keys of the ordered dictionary in the correct order.
public var orderedKeys: OrderedDictionaryKeys<Key, Value> {
return self.lazy.map { $0.key }
}
// MARK: - Managing Content Using Keys
/// A collection containing just the values of the ordered dictionary in the correct order.
public var orderedValues: OrderedDictionaryValues<Key, Value> {
return self.lazy.map { $0.value }
}
// ======================================================= //
// MARK: - Dictionary
// ======================================================= //
/// Converts itself to a common unsorted dictionary.
public var unorderedDictionary: Dictionary<Key, Value> {
return _keysToValues
}
// ======================================================= //
// MARK: - Indices
// ======================================================= //
/// The indices that are valid for subscripting the ordered dictionary.
public var indices: Indices {
return _orderedKeys.indices
}
/// The position of the first key-value pair in a non-empty ordered dictionary.
public var startIndex: Index {
return _orderedKeys.startIndex
}
/// The position which is one greater than the position of the last valid key-value pair in the
/// ordered dictionary.
public var endIndex: Index {
return _orderedKeys.endIndex
}
/// Returns the position immediately after the given index.
public func index(after i: Index) -> Index {
return _orderedKeys.index(after: i)
}
/// Returns the position immediately before the given index.
public func index(before i: Index) -> Index {
return _orderedKeys.index(before: i)
}
// ======================================================= //
// MARK: - Slices
// ======================================================= //
/// Accesses a contiguous subrange of the ordered dictionary.
///
/// - Parameter bounds: A range of the ordered dictionary's indices. The bounds of the range
/// must be valid indices of the ordered dictionary.
/// - Returns: The slice view at the ordered dictionary in the specified subrange.
public subscript(bounds: Range<Index>) -> SubSequence {
return OrderedDictionarySlice(base: self, bounds: bounds)
}
// ======================================================= //
// MARK: - Key-based Access
// ======================================================= //
/// Accesses the value associated with the given key for reading and writing.
///
/// This key-based subscript returns the value for the given key if the key is found in the
/// ordered dictionary, or `nil` if the key is not found.
///
/// When you assign a value for a key and that key already exists, the ordered dictionary
/// overwrites the existing value and preservers the index of the key-value pair. If the ordered
/// dictionary does not contain the key, a new key-value pair is appended to the end of the
/// ordered dictionary.
///
/// If you assign `nil` as the value for the given key, the ordered dictionary removes that key
/// and its associated value if it exists.
///
/// - Parameter key: The key to find in the ordered dictionary.
/// - Returns: The value associated with `key` if `key` is in the ordered dictionary; otherwise,
/// `nil`.
public subscript(key: Key) -> Value? {
get {
return keysToValues[key]
return value(forKey: key)
}
set(newValue) {
if let newValue = newValue {
updateValue(newValue, forKey: key)
} else {
removeValueForKey(key)
removeValue(forKey: key)
}
}
}
public mutating func updateValue(value: Value, forKey key: Key) -> Value? {
if orderedKeys.contains(key) {
guard let currentValue = keysToValues[key] else { fatalError("Inconsistency error occured in OrderedDictionary.") }
keysToValues[key] = value
/// Returns a Boolean value indicating whether the ordered dictionary contains the given key.
///
/// - Parameter key: The key to be looked up.
/// - Returns: `true` if the ordered dictionary contains the given key; otherwise, `false`.
public func containsKey(_ key: Key) -> Bool {
return _keysToValues[key] != nil
}
/// Returns the value associated with the given key if the key is found in the ordered
/// dictionary, or `nil` if the key is not found.
///
/// - Parameter key: The key to find in the ordered dictionary.
/// - Returns: The value associated with `key` if `key` is in the ordered dictionary; otherwise,
/// `nil`.
public func value(forKey key: Key) -> Value? {
return _keysToValues[key]
}
/// Updates the value stored in the ordered dictionary for the given key, or appends a new
/// key-value pair if the key does not exist.
///
/// - Parameter value: The new value to add to the ordered dictionary.
/// - Parameter key: The key to associate with `value`. If `key` already exists in the ordered
/// dictionary, `value` replaces the existing associated value. If `key` is not already a key
/// of the ordered dictionary, the `(key, value)` pair is appended at the end of the ordered
/// dictionary.
@discardableResult
public mutating func updateValue(_ value: Value, forKey key: Key) -> Value? {
if containsKey(key) {
let currentValue = _unsafeValue(forKey: key)
_keysToValues[key] = value
return currentValue
} else {
orderedKeys.append(key)
keysToValues[key] = value
_orderedKeys.append(key)
_keysToValues[key] = value
return nil
}
}
public mutating func removeValueForKey(key: Key) -> Value? {
if let index = orderedKeys.indexOf(key) {
orderedKeys.removeAtIndex(index)
guard let currentValue = keysToValues[key] else { fatalError("Inconsistency error occured in OrderedDictionary.") }
keysToValues[key] = nil
return currentValue
} else {
return nil
}
}
public mutating func removeAll(keepCapacity keepCapacity: Bool = true) {
orderedKeys.removeAll(keepCapacity: keepCapacity)
keysToValues.removeAll(keepCapacity: keepCapacity)
}
// MARK: - Managing Content Using Indexes
public subscript(index: Index) -> Element {
get {
if let element = elementAtIndex(index) {
return element
} else {
fatalError("Index out of bounds in OrderedDictionary.")
}
}
set(newValue) {
updateElement(newValue, atIndex: index)
}
}
public func indexForKey(key: Key) -> Index? {
return orderedKeys.indexOf(key)
}
public func elementAtIndex(index: Index) -> Element? {
guard orderedKeys.indices.contains(index) else { return nil }
/// Removes the given key and its associated value from the ordered dictionary.
///
/// If the key is found in the ordered dictionary, this method returns the key's associated
/// value. On removal, the indices of the ordered dictionary are invalidated. If the key is
/// not found in the ordered dictionary, this method returns `nil`.
///
/// - Parameter key: The key to remove along with its associated value.
/// - Returns: The value that was removed, or `nil` if the key was not present in the
/// ordered dictionary.
///
/// - SeeAlso: remove(at:)
@discardableResult
public mutating func removeValue(forKey key: Key) -> Value? {
guard let index = index(forKey: key) else { return nil }
let key = orderedKeys[index]
guard let value = self.keysToValues[key] else { fatalError("Inconsistency error occured in OrderedDictionary.") }
let currentValue = self[index].value
_orderedKeys.remove(at: index)
_keysToValues[key] = nil
return currentValue
}
/// Removes all key-value pairs from the ordered dictionary and invalidates all indices.
///
/// - Parameter keepCapacity: Whether the ordered dictionary should keep its underlying storage.
/// If you pass `true`, the operation preserves the storage capacity that the collection has,
/// otherwise the underlying storage is released. The default is `false`.
public mutating func removeAll(keepingCapacity keepCapacity: Bool = false) {
_orderedKeys.removeAll(keepingCapacity: keepCapacity)
_keysToValues.removeAll(keepingCapacity: keepCapacity)
}
private func _unsafeValue(forKey key: Key) -> Value {
let value = _keysToValues[key]
precondition(value != nil, "Inconsistency error occurred in OrderedDictionary")
return value!
}
// ======================================================= //
// MARK: - Index-based Access
// ======================================================= //
/// Accesses the key-value pair at the specified position.
///
/// The specified position has to be a valid index of the ordered dictionary. The index-base
/// subscript returns the key-value pair corresponding to the index.
///
/// - Parameter position: The position of the key-value pair to access. `position` must be
/// a valid index of the ordered dictionary and not equal to `endIndex`.
/// - Returns: A tuple containing the key-value pair corresponding to `position`.
///
/// - SeeAlso: update(:at:)
public subscript(position: Index) -> Element {
precondition(indices.contains(position), "OrderedDictionary index is out of range")
let key = _orderedKeys[position]
let value = _unsafeValue(forKey: key)
return (key, value)
}
public mutating func updateElement(element: Element, atIndex index: Index) -> Element? {
// TODO: Handle index out of range
let currentElement = elementAtIndex(index)
if currentElement != nil {
keysToValues.removeValueForKey(element.0)
}
let (newKey, newValue) = (element.0, element.1)
orderedKeys[index] = newKey
keysToValues[newKey] = newValue
return currentElement
/// Returns the index for the given key.
///
/// - Parameter key: The key to find in the ordered dictionary.
/// - Returns: The index for `key` and its associated value if `key` is in the ordered
/// dictionary; otherwise, `nil`.
public func index(forKey key: Key) -> Index? {
return _orderedKeys.index(of: key)
}
public mutating func removeAtIndex(index: Index) -> Element? {
if let element = elementAtIndex(index) {
orderedKeys.removeAtIndex(index)
keysToValues.removeValueForKey(element.0)
return element
} else {
return nil
}
/// Returns the key-value pair at the specified index, or `nil` if there is no key-value pair
/// at that index.
///
/// - Parameter index: The index of the key-value pair to be looked up. `index` does not have to
/// be a valid index.
/// - Returns: A tuple containing the key-value pair corresponding to `index` if the index is
/// valid; otherwise, `nil`.
public func elementAt(_ index: Index) -> Element? {
return indices.contains(index) ? self[index] : nil
}
// MARK: - Description
public var description: String {
let content = map({ "\($0.0): \($0.1)" }).joinWithSeparator(", ")
return "[\(content)]"
/// Checks whether the given key-value pair can be inserted into to ordered dictionary by
/// validating the presence of the key.
///
/// - Parameter newElement: The key-value pair to be inserted into the ordered dictionary.
/// - Returns: `true` if the key-value pair can be safely inserted; otherwise, `false`.
///
/// - SeeAlso: canInsert(key:)
/// - SeeAlso: canInsert(at:)
@available(*, deprecated, message: "Use canInsert(key:) with the element's key instead")
public func canInsert(_ newElement: Element) -> Bool {
return canInsert(key: newElement.key)
}
// MARK: - Backing Store
private var orderedKeys: [Key]
private var keysToValues: [Key: Value]
// MARK: - SequenceType & Indexable Conformance
public func generate() -> AnyGenerator<Element> {
var nextIndex = 0
let lastIndex = self.count
return anyGenerator {
guard nextIndex < lastIndex else { return nil }
let nextKey = self.orderedKeys[nextIndex]
guard let nextValue = self.keysToValues[nextKey] else { fatalError("Inconsistency error occured in OrderedDictionary.") }
let element = (nextKey, nextValue)
nextIndex++
return element
}
/// Checks whether a key-value pair with the given key can be inserted into the ordered
/// dictionary by validating its presence.
///
/// - Parameter key: The key to be inserted into the ordered dictionary.
/// - Returns: `true` if the key can safely be inserted; ortherwise, `false`.
///
/// - SeeAlso: canInsert(at:)
public func canInsert(key: Key) -> Bool {
return !containsKey(key)
}
public var startIndex: Index { return orderedKeys.startIndex }
/// Checks whether a new key-value pair can be inserted into the ordered dictionary at the
/// given index.
///
/// - Parameter index: The index the new key-value pair should be inserted at.
/// - Returns: `true` if a new key-value pair can be inserted at the specified index; otherwise,
/// `false`.
///
/// - SeeAlso: canInsert(key:)
public func canInsert(at index: Index) -> Bool {
return index >= startIndex && index <= endIndex
}
public var endIndex: Index { return orderedKeys.endIndex }
/// Inserts a new key-value pair at the specified position.
///
/// If the key of the inserted pair already exists in the ordered dictionary, a runtime error
/// is triggered. Use `canInsert(_:)` for performing a check first, so that this method can
/// be executed safely.
///
/// - Parameter newElement: The new key-value pair to insert into the ordered dictionary. The
/// key contained in the pair must not be already present in the ordered dictionary.
/// - Parameter index: The position at which to insert the new key-value pair. `index` must be
/// a valid index of the ordered dictionary or equal to `endIndex` property.
///
/// - SeeAlso: canInsert(key:)
/// - SeeAlso: canInsert(at:)
/// - SeeAlso: update(:at:)
public mutating func insert(_ newElement: Element, at index: Index) {
precondition(canInsert(key: newElement.key), "Cannot insert duplicate key in OrderedDictionary")
precondition(canInsert(at: index), "Cannot insert at invalid index in OrderedDictionary")
let (key, value) = newElement
_orderedKeys.insert(key, at: index)
_keysToValues[key] = value
}
/// Checks whether the key-value pair at the given index can be updated with the given key-value
/// pair. This is not the case if the key of the updated element is already present in the
/// ordered dictionary and located at another index than the updated one.
///
/// Although this is a checking method, a valid index has to be provided.
///
/// - Parameter newElement: The key-value pair to be set at the specified position.
/// - Parameter index: The position at which to set the key-value pair. `index` must be a valid
/// index of the ordered dictionary.
public func canUpdate(_ newElement: Element, at index: Index) -> Bool {
var keyPresentAtIndex = false
return _canUpdate(newElement, at: index, keyPresentAtIndex: &keyPresentAtIndex)
}
/// Updates the key-value pair located at the specified position.
///
/// If the key of the updated pair already exists in the ordered dictionary *and* is located at
/// a different position than the specified one, a runtime error is triggered. Use
/// `canUpdate(_:at:)` for performing a check first, so that this method can be executed safely.
///
/// - Parameter newElement: The key-value pair to be set at the specified position.
/// - Parameter index: The position at which to set the key-value pair. `index` must be a valid
/// index of the ordered dictionary.
///
/// - SeeAlso: canUpdate(_:at:)
/// - SeeAlso: insert(:at:)
@discardableResult
public mutating func update(_ newElement: Element, at index: Index) -> Element? {
// Store the flag indicating whether the key of the inserted element
// is present at the updated index
var keyPresentAtIndex = false
precondition(
_canUpdate(newElement, at: index, keyPresentAtIndex: &keyPresentAtIndex),
"OrderedDictionary update duplicates key"
)
// Decompose the element
let (key, value) = newElement
// Load the current element at the index
let replacedElement = self[index]
// If its key differs, remove its associated value
if (!keyPresentAtIndex) {
_keysToValues.removeValue(forKey: replacedElement.key)
}
// Store the new position of the key and the new value associated with the key
_orderedKeys[index] = key
_keysToValues[key] = value
return replacedElement
}
/// Removes and returns the key-value pair at the specified position if there is any key-value
/// pair, or `nil` if there is none.
///
/// - Parameter index: The position of the key-value pair to remove.
/// - Returns: The element at the specified index, or `nil` if the position is not taken.
///
/// - SeeAlso: removeValue(forKey:)
@discardableResult
public mutating func remove(at index: Index) -> Element? {
guard let element = elementAt(index) else { return nil }
_orderedKeys.remove(at: index)
_keysToValues.removeValue(forKey: element.key)
return element
}
private func _canUpdate(
_ newElement: Element,
at index: Index,
keyPresentAtIndex: inout Bool
) -> Bool {
precondition(indices.contains(index), "OrderedDictionary index is out of range")
let currentIndexOfKey = self.index(forKey: newElement.key)
let keyNotPresent = currentIndexOfKey == nil
keyPresentAtIndex = currentIndexOfKey == index
return keyNotPresent || keyPresentAtIndex
}
// ======================================================= //
// MARK: - Removing First & Last Elements
// ======================================================= //
/// Removes and returns the first key-value pair of the ordered dictionary if it is not empty.
public mutating func popFirst() -> Element? {
guard !isEmpty else { return nil }
return remove(at: startIndex)
}
/// Removes and returns the last key-value pair of the ordered dictionary if it is not empty.
public mutating func popLast() -> Element? {
guard !isEmpty else { return nil }
return remove(at: index(before: endIndex))
}
/// Removes and returns the first key-value pair of the ordered dictionary.
public mutating func removeFirst() -> Element {
precondition(!isEmpty, "Cannot remove key-value pairs from empty OrderedDictionary")
return remove(at: startIndex)!
}
/// Removes and returns the last key-value pair of the ordered dictionary.
public mutating func removeLast() -> Element {
precondition(!isEmpty, "Cannot remove key-value pairs from empty OrderedDictionary")
return remove(at: index(before: endIndex))!
}
// ======================================================= //
// MARK: - Moving Elements
// ======================================================= //
/// Moves an existing key-value pair specified by the given key to the new index by removing it
/// from its original index first and inserting it at the new index. If the movement is
/// actually performed, the previous index of the key-value pair is returned. Otherwise, `nil`
/// is returned.
///
/// - Parameter key: The key specifying the key-value pair to move.
/// - Parameter newIndex: The new index the key-value pair should be moved to.
/// - Returns: The previous index of the key-value pair if it was sucessfully moved.
@discardableResult
public mutating func moveElement(forKey key: Key, to newIndex: Index) -> Index? {
// Load the previous index and return nil if the index is not found.
guard let previousIndex = index(forKey: key) else { return nil }
// If the previous and new indices match, threat it as if the movement was already
// performed.
guard previousIndex != newIndex else { return previousIndex }
// Remove the value for the key at its original index.
let value = removeValue(forKey: key)!
// Validate the new index.
precondition(canInsert(at: newIndex), "Cannot move to invalid index in OrderedDictionary")
// Insert the element at the new index.
insert((key: key, value: value), at: newIndex)
return previousIndex
}
// ======================================================= //
// MARK: - Sorting Elements
// ======================================================= //
/// Sorts the ordered dictionary in place, using the given predicate as the comparison between
/// elements.
///
/// The predicate must be a *strict weak ordering* over the elements.
///
/// - Parameter areInIncreasingOrder: A predicate that returns `true` if its first argument
/// should be ordered before its second argument; otherwise, `false`.
///
/// - SeeAlso: MutableCollection.sort(by:), sorted(by:)
public mutating func sort(
by areInIncreasingOrder: (Element, Element) throws -> Bool
) rethrows {
_orderedKeys = try _sortedElements(by: areInIncreasingOrder).map { $0.key }
}
/// Returns a new ordered dictionary, sorted using the given predicate as the comparison between
/// elements.
///
/// The predicate must be a *strict weak ordering* over the elements.
///
/// - Parameter areInIncreasingOrder: A predicate that returns `true` if its first argument
/// should be ordered before its second argument; otherwise, `false`.
/// - Returns: A new ordered dictionary sorted according to the predicate.
///
/// - SeeAlso: MutableCollection.sorted(by:), sort(by:)
/// - MutatingVariant: sort
public func sorted(
by areInIncreasingOrder: (Element, Element) throws -> Bool
) rethrows -> OrderedDictionary<Key, Value> {
return OrderedDictionary(try _sortedElements(by: areInIncreasingOrder))
}
private func _sortedElements(
by areInIncreasingOrder: (Element, Element) throws -> Bool
) rethrows -> [Element] {
return try sorted(by: areInIncreasingOrder)
}
// ======================================================= //
// MARK: - Internal Storage
// ======================================================= //
/// The backing storage for the ordered keys.
fileprivate var _orderedKeys = [Key]()
/// The backing storage for the mapping of keys to values.
fileprivate var _keysToValues = [Key: Value]()
}
// ======================================================= //
// MARK: - Subtypes
// ======================================================= //
#if swift(>=4.1)
/// A view into an ordered dictionary whose indices are a subrange of the indices of the ordered
/// dictionary.
public typealias OrderedDictionarySlice<Key: Hashable, Value> = Slice<OrderedDictionary<Key, Value>>
/// A collection containing the keys of the ordered dictionary.
///
/// Under the hood this is a lazily evaluated bidirectional collection deriving the keys from
/// the base ordered dictionary on-the-fly.
public typealias OrderedDictionaryKeys<Key: Hashable, Value> = LazyMapCollection<OrderedDictionary<Key, Value>, Key>
/// A collection containing the values of the ordered dictionary.
///
/// Under the hood this is a lazily evaluated bidirectional collection deriving the values from
/// the base ordered dictionary on-the-fly.
public typealias OrderedDictionaryValues<Key: Hashable, Value> = LazyMapCollection<OrderedDictionary<Key, Value>, Value>
#else
/// A view into an ordered dictionary whose indices are a subrange of the indices of the ordered
/// dictionary.
public typealias OrderedDictionarySlice<Key: Hashable, Value> = BidirectionalSlice<OrderedDictionary<Key, Value>>
/// A collection containing the keys of the ordered dictionary.
///
/// Under the hood this is a lazily evaluated bidirectional collection deriving the keys from
/// the base ordered dictionary on-the-fly.
public typealias OrderedDictionaryKeys<Key: Hashable, Value> = LazyMapBidirectionalCollection<OrderedDictionary<Key, Value>, Key>
/// A collection containing the values of the ordered dictionary.
///
/// Under the hood this is a lazily evaluated bidirectional collection deriving the values from
/// the base ordered dictionary on-the-fly.
public typealias OrderedDictionaryValues<Key: Hashable, Value> = LazyMapBidirectionalCollection<OrderedDictionary<Key, Value>, Value>
#endif
// ======================================================= //
// MARK: - Literals
// ======================================================= //
extension OrderedDictionary: ExpressibleByArrayLiteral {
/// Creates an ordered dictionary initialized from an array literal containing a list of
/// key-value pairs.
public init(arrayLiteral elements: Element...) {
self.init(elements)
}
}
extension OrderedDictionary: ExpressibleByDictionaryLiteral {
/// Creates an ordered dictionary initialized from a dictionary literal.
public init(dictionaryLiteral elements: (Key, Value)...) {
self.init(elements.map { element in
let (key, value) = element
return (key: key, value: value)
})
}
}
// ======================================================= //
// MARK: - Equatable Conformance
// ======================================================= //
#if swift(>=4.1)
extension OrderedDictionary: Equatable where Value: Equatable {}
#endif
extension OrderedDictionary where Value: Equatable {
/// Returns a Boolean value that indicates whether the two given ordered dictionaries with
/// equatable values are equal.
public static func == (lhs: OrderedDictionary, rhs: OrderedDictionary) -> Bool {
return lhs._orderedKeys == rhs._orderedKeys
&& lhs._keysToValues == rhs._keysToValues
}
}
// ======================================================= //
// MARK: - Dictionary Extension
// ======================================================= //
extension Dictionary {
/// Returns an ordered dictionary containing the key-value pairs from the dictionary, sorted
/// using the given sort function.
///
/// - Parameter areInIncreasingOrder: The sort function which compares the key-value pairs.
/// - Returns: The ordered dictionary.
/// - SeeAlso: OrderedDictionary.init(unsorted:areInIncreasingOrder:)
public func sorted(
by areInIncreasingOrder: (Element, Element) throws -> Bool
) rethrows -> OrderedDictionary<Key, Value> {
return try OrderedDictionary(
unsorted: self,
areInIncreasingOrder: areInIncreasingOrder
)
}
}
+2 -2
View File
@@ -15,13 +15,13 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>0.1</string>
<string>2.2.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2015 Lukas Kubanek. All rights reserved.</string>
<string>Copyright © 2015-2019 Lukas Kubanek. All rights reserved.</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
+568 -98
View File
@@ -1,160 +1,630 @@
//
// OrderedDictionaryTests.swift
// OrderedDictionaryTests
//
// Created by Lukas Kubanek on 29/08/15.
// Copyright © 2015 Lukas Kubanek. All rights reserved.
//
import XCTest
import Nimble
import OrderedDictionary
import Foundation
import XCTest
#if !swift(>=4.1)
/// This is a shim for testing the equality in Swift <4.1.
public func XCTAssertEqual<K, V: Equatable>(
_ expression1: OrderedDictionary<K, V>,
_ expression2: OrderedDictionary<K, V>,
_ message: @autoclosure () -> String = "",
file: StaticString = #file,
line: UInt = #line
) {
return XCTAssertTrue(
expression1 == expression2,
message,
file: file,
line: line
)
}
#endif
struct TestValue: Equatable {
var string: String
static func == (lhs: TestValue, rhs: TestValue) -> Bool {
return lhs.string == rhs.string
}
}
class OrderedDictionaryTests: XCTestCase {
var orderedDictionary: OrderedDictionary<String, Int>!
// ======================================================= //
// MARK: - Initialization
// ======================================================= //
override func setUp() {
orderedDictionary = [
func testInitializationUsingArrayLiteral() {
let actual: OrderedDictionary<String, Int> = [
("A", 1),
("B", 2),
("C", 3)
]
let expected = OrderedDictionary<String, Int>([
(key: "A", value: 1),
(key: "B", value: 2),
(key: "C", value: 3)
])
XCTAssertEqual(actual, expected)
}
// MARK: - Content
func testInitializedContent() {
expect(self.orderedDictionary.count) == 3
func testInitializationUsingDictionaryLiteral() {
let actual: OrderedDictionary<String, Int> = [
"A": 1,
"B": 2,
"C": 3
]
expect(self.orderedDictionary["A"]) == 1
expect(self.orderedDictionary.indexForKey("A")) == 0
let expected = OrderedDictionary<String, Int>([
(key: "A", value: 1),
(key: "B", value: 2),
(key: "C", value: 3)
])
expect(self.orderedDictionary["B"]) == 2
expect(self.orderedDictionary.indexForKey("B")) == 1
expect(self.orderedDictionary["C"]) == 3
expect(self.orderedDictionary.indexForKey("C")) == 2
XCTAssertEqual(actual, expected)
}
func testElementsGenerator() {
for entry in self.orderedDictionary.enumerate() {
expect(self.orderedDictionary[entry.index].0) == entry.element.0
expect(self.orderedDictionary[entry.index].1) == entry.element.1
func testInitializationUsingValuesAndKeyProviderClosure() {
let actual = OrderedDictionary(
values: [1, 2, 3],
keyedBy: { "\($0)" }
)
let expected = OrderedDictionary<String, Int>([
(key: "1", value: 1),
(key: "2", value: 2),
(key: "3", value: 3)
])
XCTAssertEqual(actual, expected)
}
func testInitializationUsingValuesAnyKeyPath() {
let actual = OrderedDictionary(
values: [
TestValue(string: "A"),
TestValue(string: "B"),
TestValue(string: "C")
],
keyedBy: \.string
)
let expected = OrderedDictionary<String, TestValue>([
(key: "A", value: TestValue(string: "A")),
(key: "B", value: TestValue(string: "B")),
(key: "C", value: TestValue(string: "C"))
])
XCTAssertEqual(actual, expected)
}
func testInitializationUsingUnsortedDictionaryAndSortFunction() {
let actual = OrderedDictionary(
unsorted: [
2: "foo",
1: "bar",
4: "baz",
5: "bat",
3: "bam"
],
areInIncreasingOrder: { $0.key < $1.key }
)
let expected = OrderedDictionary([
(key: 1, value: "bar"),
(key: 2, value: "foo"),
(key: 3, value: "bam"),
(key: 4, value: "baz"),
(key: 5, value: "bat")
])
XCTAssertEqual(actual, expected)
}
func testCreationFromDictionary() {
let actual = [
2: "foo",
1: "bar",
4: "baz",
5: "bat",
3: "bam"
].sorted(by: { $0.key < $1.key })
let expected = OrderedDictionary([
(key: 1, value: "bar"),
(key: 2, value: "foo"),
(key: 3, value: "bam"),
(key: 4, value: "baz"),
(key: 5, value: "bat")
])
XCTAssertEqual(actual, expected)
}
// ======================================================= //
// MARK: - Content Access
// ======================================================= //
func testAccessingContent() {
let orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3]
XCTAssertEqual(orderedDictionary.count, 3)
XCTAssertEqual(orderedDictionary["A"], 1)
XCTAssertEqual(orderedDictionary.value(forKey: "A"), 1)
XCTAssertEqual(orderedDictionary.index(forKey: "A"), 0)
XCTAssertTrue(orderedDictionary.containsKey("A"))
XCTAssertTrue(orderedDictionary[0] == ("A", 1))
XCTAssertEqual(orderedDictionary["B"], 2)
XCTAssertEqual(orderedDictionary.value(forKey: "B"), 2)
XCTAssertEqual(orderedDictionary.index(forKey: "B"), 1)
XCTAssertTrue(orderedDictionary.containsKey("B"))
XCTAssertTrue(orderedDictionary[1] == ("B", 2))
XCTAssertEqual(orderedDictionary["C"], 3)
XCTAssertEqual(orderedDictionary.value(forKey: "C"), 3)
XCTAssertEqual(orderedDictionary.index(forKey: "C"), 2)
XCTAssertTrue(orderedDictionary.containsKey("C"))
XCTAssertTrue(orderedDictionary[2] == ("C", 3))
}
func testCreatingIterator() {
let orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3]
var iterator = orderedDictionary.makeIterator()
let indexes = [0, 1, 2]
var indexesIterator = indexes.makeIterator()
while let (actualKey, actualValue) = iterator.next() {
let index = indexesIterator.next()
let (expectedKey, expectedValue) = orderedDictionary[index!]
XCTAssertEqual(actualKey, expectedKey)
XCTAssertEqual(actualValue, expectedValue)
}
XCTAssertNil(iterator.next())
XCTAssertNil(indexesIterator.next())
}
func testAccessingOrderedKeys() {
let orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3]
let actual = Array(orderedDictionary.orderedKeys)
let expected = ["A", "B", "C"]
XCTAssertEqual(actual, expected)
}
func testAccessingOrderedValues() {
let orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3]
let actual = Array(orderedDictionary.orderedValues)
let expected = [1, 2, 3]
XCTAssertEqual(actual, expected)
}
func testAccessingUnsortedDictionary() {
let orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3]
let actual = orderedDictionary.unorderedDictionary
let expected = ["A": 1, "B": 2, "C": 3]
XCTAssertEqual(actual, expected)
}
// ======================================================= //
// MARK: - Key-based Modifications
// ======================================================= //
func testKeyBasedSubscript() {
self.orderedDictionary["A"] = 5
self.orderedDictionary["D"] = 10
self.orderedDictionary["B"] = nil
func testKeyBasedModifications() {
var orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3]
expect(self.orderedDictionary.count) == 3
orderedDictionary["A"] = 5
orderedDictionary["D"] = 10
orderedDictionary["B"] = nil
expect(self.orderedDictionary["A"]) == 5
expect(self.orderedDictionary.indexForKey("A")) == 0
XCTAssertEqual(orderedDictionary.count, 3)
expect(self.orderedDictionary["B"]).to(beNil())
expect(self.orderedDictionary.indexForKey("B")).to(beNil())
XCTAssertEqual(orderedDictionary["A"], 5)
XCTAssertEqual(orderedDictionary.index(forKey: "A"), 0)
XCTAssertTrue(orderedDictionary.containsKey("A"))
expect(self.orderedDictionary["C"]) == 3
expect(self.orderedDictionary.indexForKey("C")) == 1
XCTAssertNil(orderedDictionary["B"])
XCTAssertNil(orderedDictionary.index(forKey: "B"))
XCTAssertFalse(orderedDictionary.containsKey("B"))
expect(self.orderedDictionary["D"]) == 10
expect(self.orderedDictionary.indexForKey("D")) == 2
XCTAssertEqual(orderedDictionary["C"], 3)
XCTAssertEqual(orderedDictionary.index(forKey: "C"), 1)
XCTAssertTrue(orderedDictionary.containsKey("C"))
XCTAssertEqual(orderedDictionary["D"], 10)
XCTAssertEqual(orderedDictionary.index(forKey: "D"), 2)
XCTAssertTrue(orderedDictionary.containsKey("D"))
}
// MARK: - Index-based Modifications
// ======================================================= //
// MARK: - Index-based Insertions
// ======================================================= //
func testIndexBasedSubscriptForRetrievingValues() {
let elementAtIndex0 = self.orderedDictionary[0]
expect(elementAtIndex0.0) == "A"
expect(elementAtIndex0.1) == 1
func testIndexBasedInsertionsWithUniqueKeys() {
var orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3]
orderedDictionary.insert((key: "T", value: 15), at: 0)
orderedDictionary.insert((key: "U", value: 16), at: 2)
orderedDictionary.insert((key: "V", value: 17), at: 5)
orderedDictionary.insert((key: "W", value: 18), at: 2)
let actual = orderedDictionary
let elementAtIndex1 = self.orderedDictionary[1]
expect(elementAtIndex1.0) == "B"
expect(elementAtIndex1.1) == 2
let expected: OrderedDictionary<String, Int> = ["T": 15, "A": 1, "W": 18, "U": 16, "B": 2, "C": 3, "V": 17]
let elementAtIndex2 = self.orderedDictionary[2]
expect(elementAtIndex2.0) == "C"
expect(elementAtIndex2.1) == 3
XCTAssertEqual(actual, expected)
}
func testIndexBasedSubscriptForSettingValues() {
self.orderedDictionary[0] = ("F", 10)
self.orderedDictionary[1] = ("B", 5)
func testIndexBasedInsertionWithDuplicateKey() {
let orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3]
let invalidKey = "A"
let elementAtIndex0 = self.orderedDictionary[0]
expect(elementAtIndex0.0) == "F"
expect(elementAtIndex0.1) == 10
XCTAssertFalse(orderedDictionary.canInsert(key: invalidKey))
}
func testIndexBasedInsertionWithNegativeIndex() {
let orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3]
let invalidIndex = -1
let elementAtIndex1 = self.orderedDictionary[1]
expect(elementAtIndex1.0) == "B"
expect(elementAtIndex1.1) == 5
XCTAssertFalse(orderedDictionary.canInsert(at: invalidIndex))
}
func testIndexBasedInsertionWithIndexOutOfBounds() {
let orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3]
let invalidIndex = 4
let elementAtIndex2 = self.orderedDictionary[2]
expect(elementAtIndex2.0) == "C"
expect(elementAtIndex2.1) == 3
XCTAssertFalse(orderedDictionary.canInsert(at: invalidIndex))
}
// ======================================================= //
// MARK: - Index-based Updates
// ======================================================= //
func testIndexBasedUpdateMethodWithNewUniqueKey() {
var orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3]
let previousElement = orderedDictionary.update((key: "D", value: 4), at: 1)
XCTAssertEqual(orderedDictionary.count, 3)
XCTAssertTrue(previousElement! == ("B", 2))
let actual = orderedDictionary
let expected: OrderedDictionary<String, Int> = ["A": 1, "D": 4, "C": 3]
XCTAssertEqual(actual, expected)
}
func testIndexBasedUpdateMethodByReplacingSameKey() {
var orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3]
let previousElement = orderedDictionary.update((key: "B", value: 42), at: 1)
XCTAssertEqual(orderedDictionary.count, 3)
XCTAssertTrue(previousElement! == ("B", 2))
let actual = orderedDictionary
let expected: OrderedDictionary<String, Int> = ["A": 1, "B": 42, "C": 3]
XCTAssertEqual(actual, expected)
}
func testIndexBasedUpdateMethodByDuplicatingKey() {
let orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3]
let element = (key: "A", value: 42)
XCTAssertTrue(orderedDictionary.canUpdate(element, at: 0))
XCTAssertFalse(orderedDictionary.canUpdate(element, at: 1))
XCTAssertFalse(orderedDictionary.canUpdate(element, at: 2))
}
func testRetrievingElementAtNonExistentIndex() {
expect(self.orderedDictionary.elementAtIndex(10)).to(beNil())
let orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3]
XCTAssertNil(orderedDictionary.elementAt(42))
}
// MARK: - Removal
// ======================================================= //
// MARK: - Content Removal
// ======================================================= //
func testRemoveAll() {
self.orderedDictionary.removeAll()
var orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3]
expect(self.orderedDictionary.count) == 0
orderedDictionary.removeAll()
XCTAssertEqual(orderedDictionary.count, 0)
}
func testRemovalForKey() {
let removedValue1 = self.orderedDictionary.removeValueForKey("A")
let removedValue2 = self.orderedDictionary.removeValueForKey("K")
func testKeyBasedRemoval() {
var orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3]
expect(removedValue1) == 1
expect(removedValue2).to(beNil())
let removedValue1 = orderedDictionary.removeValue(forKey: "A")
let removedValue2 = orderedDictionary.removeValue(forKey: "K")
expect(self.orderedDictionary.count) == 2
XCTAssertEqual(removedValue1, 1)
XCTAssertNil(removedValue2)
expect(self.orderedDictionary["A"]).to(beNil())
expect(self.orderedDictionary.indexForKey("A")).to(beNil())
XCTAssertEqual(orderedDictionary.count, 2)
expect(self.orderedDictionary["B"]) == 2
expect(self.orderedDictionary.indexForKey("B")) == 0
XCTAssertNil(orderedDictionary["A"])
XCTAssertNil(orderedDictionary.index(forKey: "A"))
expect(self.orderedDictionary["C"]) == 3
expect(self.orderedDictionary.indexForKey("C")) == 1
XCTAssertEqual(orderedDictionary["B"], 2)
XCTAssertEqual(orderedDictionary.index(forKey: "B"), 0)
XCTAssertEqual(orderedDictionary["C"], 3)
XCTAssertEqual(orderedDictionary.index(forKey: "C"), 1)
}
func testIndexBasedRemoval() {
var orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3, "D": 4]
let (actualKey1, actualValue1) = orderedDictionary.remove(at: 0)!
let (expectedKey1, expectedValue1) = ("A", 1)
XCTAssertEqual(actualKey1, expectedKey1)
XCTAssertEqual(actualValue1, expectedValue1)
let (actualKey2, actualValue2) = orderedDictionary.remove(at: 2)!
let (expectedKey2, expectedValue2) = ("D", 4)
XCTAssertEqual(actualKey2, expectedKey2)
XCTAssertEqual(actualValue2, expectedValue2)
let nonExistentElement = orderedDictionary.remove(at: 42)
XCTAssertNil(nonExistentElement)
let actual = orderedDictionary
let expected: OrderedDictionary<String, Int> = ["B": 2, "C": 3]
XCTAssertEqual(actual, expected)
}
func testPopFirstEmpty() {
var orderedDictionary: OrderedDictionary<String, Int> = []
let first = orderedDictionary.popFirst()
XCTAssertNil(first)
}
func testPopFirstNonEmpty() {
var orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3, "D": 4]
let (actualKey, actualValue) = orderedDictionary.popFirst()!
let (expectedKey, expectedValue) = ("A", 1)
XCTAssertEqual(actualKey, expectedKey)
XCTAssertEqual(actualValue, expectedValue)
let actual = orderedDictionary
let expected: OrderedDictionary<String, Int> = ["B": 2, "C": 3, "D": 4]
XCTAssertEqual(actual, expected)
}
func testRemovalAtIndex() {
let removedElement1 = self.orderedDictionary.removeAtIndex(1)
let removedElement2 = self.orderedDictionary.removeAtIndex(0)
let removedElement3 = self.orderedDictionary.removeAtIndex(5)
func testPopLastEmpty() {
var orderedDictionary: OrderedDictionary<String, Int> = []
let last = orderedDictionary.popLast()
expect(removedElement1?.0) == "B"
expect(removedElement1?.1) == 2
expect(removedElement2?.0) == "A"
expect(removedElement2?.1) == 1
expect(removedElement3).to(beNil())
expect(self.orderedDictionary.count) == 1
let elementAtIndex0 = self.orderedDictionary[0]
expect(elementAtIndex0.0) == "C"
expect(elementAtIndex0.1) == 3
XCTAssertNil(last)
}
func testPopLastNonEmpty() {
var orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3, "D": 4]
let (actualKey, actualValue) = orderedDictionary.popLast()!
let (expectedKey, expectedValue) = ("D", 4)
XCTAssertEqual(actualKey, expectedKey)
XCTAssertEqual(actualValue, expectedValue)
let actual = orderedDictionary
let expected: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3]
XCTAssertEqual(actual, expected)
}
func testRemoveFirstNonEmpty() {
var orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3, "D": 4]
let (actualKey, actualValue) = orderedDictionary.removeFirst()
let (expectedKey, expectedValue) = ("A", 1)
XCTAssertEqual(actualKey, expectedKey)
XCTAssertEqual(actualValue, expectedValue)
let actual = orderedDictionary
let expected: OrderedDictionary<String, Int> = ["B": 2, "C": 3, "D": 4]
XCTAssertEqual(actual, expected)
}
func testRemoveLastNonEmpty() {
var orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3, "D": 4]
let (actualKey, actualValue) = orderedDictionary.removeLast()
let (expectedKey, expectedValue) = ("D", 4)
XCTAssertEqual(actualKey, expectedKey)
XCTAssertEqual(actualValue, expectedValue)
let actual = orderedDictionary
let expected: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3]
XCTAssertEqual(actual, expected)
}
// ======================================================= //
// MARK: - Moving Elements
// ======================================================= //
func testMovingElements() {
var orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3, "D": 4]
XCTAssertEqual(orderedDictionary.moveElement(forKey: "A", to: 2), 0) // B, C, A, D
XCTAssertEqual(orderedDictionary.moveElement(forKey: "D", to: 3), 3) // B, C, A, D
XCTAssertEqual(orderedDictionary.moveElement(forKey: "C", to: 0), 1) // C, B, A, D
XCTAssertEqual(orderedDictionary.moveElement(forKey: "B", to: 3), 1) // C, A, D, B
XCTAssertEqual(orderedDictionary.moveElement(forKey: "E", to: 0), nil)
let actual = orderedDictionary
let expected: OrderedDictionary<String, Int> = ["C": 3, "A": 1, "D": 4, "B": 2]
XCTAssertEqual(actual, expected)
}
// ======================================================= //
// MARK: - Sorting Elements
// ======================================================= //
func testSortingWithMutation() {
var orderedDictionary: OrderedDictionary<String, Int> = ["E": 4, "G": 3, "A": 3, "D": 1, "B": 4]
orderedDictionary.sort { element1, element2 in
if element1.value != element2.value { return element1.value < element2.value }
return element1.key < element2.key
}
let actual = orderedDictionary
let expected: OrderedDictionary<String, Int> = ["D": 1, "A": 3, "G": 3, "B": 4, "E": 4]
XCTAssertEqual(actual, expected)
}
func testSortingWithoutMutation() {
let orderedDictionary: OrderedDictionary<String, Int> = ["E": 4, "G": 3, "A": 3, "D": 1, "B": 4]
let actual: OrderedDictionary<String, Int> = orderedDictionary.sorted { element1, element2 in
if element1.value != element2.value { return element1.value < element2.value }
return element1.key < element2.key
}
let expected: OrderedDictionary<String, Int> = ["D": 1, "A": 3, "G": 3, "B": 4, "E": 4]
XCTAssertEqual(actual, expected)
}
// ======================================================= //
// MARK: - Slices
// ======================================================= //
func testSliceAccess() {
let orderedDictionary: OrderedDictionary<String, Int> = ["A": 1, "B": 2, "C": 3, "D": 4]
let slice = orderedDictionary[2..<4]
XCTAssertEqual(slice.count, 2)
XCTAssertEqual(slice.startIndex, 2)
XCTAssertEqual(slice.endIndex, 4)
XCTAssertEqual(Array(slice.indices), [2, 3])
XCTAssert(slice[2] == (key: "C", value: 3))
XCTAssert(slice[3] == (key: "D", value: 4))
}
// ======================================================= //
// MARK: - Codable
// ======================================================= //
func testEncodingAndDecodingViaJSON() {
let orderedDictionary: OrderedDictionary<String, Int> = [
"A": 42,
"B": 100,
"C": 11
]
let jsonEncoder = JSONEncoder()
let data = try! jsonEncoder.encode(orderedDictionary)
let actualString = String(data: data, encoding: .utf8)
let expectedString = "[\"A\",42,\"B\",100,\"C\",11]"
XCTAssertEqual(actualString, expectedString)
let jsonDecoder = JSONDecoder()
let actual = try! jsonDecoder.decode(OrderedDictionary<String, Int>.self, from: data)
let expected = orderedDictionary
XCTAssertEqual(actual, expected)
}
func testEncodingAndDecodingViaPropertyList() {
let orderedDictionary: OrderedDictionary<String, Int> = [
"A": 42,
"B": 100,
"C": 11
]
let plistEncoder = PropertyListEncoder()
let data = try! plistEncoder.encode(orderedDictionary)
let plistDecoder = PropertyListDecoder()
let actual = try! plistDecoder.decode(OrderedDictionary<String, Int>.self, from: data)
let expected = orderedDictionary
XCTAssertEqual(actual, expected)
}
// ======================================================= //
// MARK: - Description
// ======================================================= //
struct DescribedValue: CustomStringConvertible, CustomDebugStringConvertible {
init(_ value: Int) { self.value = value }
let value: Int
var description: String { return "\(value)" }
var debugDescription: String { return "debug(\(value))" }
}
func testEmptyDescription() {
let orderedDictionary = OrderedDictionary<String, DescribedValue>()
let actual = orderedDictionary.description
let expected = "[:]"
XCTAssertEqual(actual, expected)
}
func testDescription() {
expect(self.orderedDictionary.description) == "[A: 1, B: 2, C: 3]"
let orderedDictionary: OrderedDictionary<String, DescribedValue> = [
"A": DescribedValue(1),
"B": DescribedValue(2),
"C": DescribedValue(3)
]
let actual = orderedDictionary.description
let expected = "[A: 1, B: 2, C: 3]"
XCTAssertEqual(actual, expected)
}
func testEmptyDebugDescription() {
let orderedDictionary = OrderedDictionary<String, DescribedValue>()
let actual = orderedDictionary.debugDescription
let expected = "[:]"
XCTAssertEqual(actual, expected)
}
func testDebugDescription() {
let orderedDictionary: OrderedDictionary<String, DescribedValue> = [
"A": DescribedValue(1),
"B": DescribedValue(2),
"C": DescribedValue(3)
]
let actual = orderedDictionary.debugDescription
let expected = "[\"A\": debug(1), \"B\": debug(2), \"C\": debug(3)]"
XCTAssertEqual(actual, expected)
}
}