diff --git a/.projlint.yml b/.projlint.yml deleted file mode 100644 index b9e8dfd..0000000 --- a/.projlint.yml +++ /dev/null @@ -1,84 +0,0 @@ -shared_variables: - rightholder: Flinesoft - project_name: HandySwift - -rules: - - xcode_build_phases: - project_path: <:project_name:>.xcodeproj - target_name: <:project_name:> iOS - run_scripts: - SwiftLint: | - if [ "${CONFIGURATION}" = "Debug" ]; then - if which swiftlint > /dev/null; then - swiftlint - else - echo "warning: SwiftLint not installed, download it from https://github.com/realm/SwiftLint" - fi - fi - - ProjLint: | - if [ "${CONFIGURATION}" = "Debug" ]; then - if which projlint > /dev/null; then - projlint lint --xcode --timeout 2 --ignore-network-errors - else - echo "warning: ProjLint not installed, download it from https://github.com/JamitLabs/ProjLint" - fi - fi - - - xcode_project_navigator: - project_path: <:project_name:>.xcodeproj - sorted: - - Frameworks/<:project_name:> - - Frameworks/SupportingFiles - - Tests/<:project_name:>Tests - - Tests/SupportingFiles - inner_group_order: - - assets - - entitlements - - plists - - strings - - others - - [code_files, interfaces] - - folders - structure: - - Frameworks: - - <:project_name:> - - SupportingFiles: - - Info.plist - - Tests: - - <:project_name:>Tests - - SupportingFiles: - - Info.plist - - RootFiles: - - beak.swift - - .projlint.yml - - .swiftlint.yml - - Package.swift - - Products - - file_content_template: - matching: - .swiftlint.yml: - template_url: "https://raw.githubusercontent.com/JamitLabs/ProjLintTemplates/master/Framework/SwiftLint.stencil" - parameters: - rightholder: <:rightholder:> - .projlint.yml: - template_url: "https://raw.githubusercontent.com/JamitLabs/ProjLintTemplates/master/Framework/ProjLint.stencil" - parameters: - rightholder: <:rightholder:> - project_name: <:project_name:> - - file_existence: - existing_paths: - - .gitignore - - .swiftlint.yml - - .sourcery/LinuxMain.stencil - - CODE_OF_CONDUCT.md - - CONTRIBUTING.md - - CHANGELOG.md - - LICENSE - - README.md - - <:project_name:>.podspec - - Package.swift - - beak.swift - - <:project_name:>.xcodeproj/xcshareddata/IDETemplateMacros.plist - - Frameworks/SupportingFiles/Info.plist - - Tests/SupportingFiles/Info.plist diff --git a/CHANGELOG.md b/CHANGELOG.md index ed69a5c..1f2216d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,28 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## [Unreleased] -### Added +### Addedge - None. ### Changed +- None. +### Deprecated +- None. +### Removed +- None. +### Fixed - None. +### Security +- None. + + +## [2.8.0] +### Added +- New `NSRange(_:in:)` initializer for converting from `Range` +- New `sum` computed property on `Sequence` types like `Array` +- New `average` computed property on `Collection` types with `Int` or `Double` elements like `[Int]` +- New `fullRange` and `fullNSRange` computed properties on `String` +### Changed +- Made some APIs available in wider contexts (like `sample` in `RandomAccessCollection` instead of `Array`) ### Deprecated - None. ### Removed diff --git a/Frameworks/HandySwift/Extensions/ArrayExtension.swift b/Frameworks/HandySwift/Extensions/ArrayExtension.swift index 25aa1f1..30e23bc 100644 --- a/Frameworks/HandySwift/Extensions/ArrayExtension.swift +++ b/Frameworks/HandySwift/Extensions/ArrayExtension.swift @@ -6,30 +6,9 @@ import Foundation extension Array { + /// A tuple representing a combination. public typealias Combination = (left: Element, right: T) - /// Returns a random element from the `Array`. - /// - /// - Returns: A random element from the array or `nil` if empty. - public var sample: Element? { - guard let randomIndex = Int(randomBelow: count) else { return nil } - return self[randomIndex] - } - - /// Returns a given number of random elements from the `Array`. - /// - /// - Parameters: - /// - size: The number of random elements wanted. - /// - Returns: An array with the given number of random elements or `nil` if empty. - public func sample(size: Int) -> [Element]? { - guard !isEmpty else { return nil } - - var sampleElements: [Element] = [] - size.times { sampleElements.append(sample!) } - - return sampleElements - } - /// Combines each element with each element of a given array. /// /// Also known as: Cartesian product. @@ -111,6 +90,51 @@ extension Array { } } +extension RandomAccessCollection where Index == Int { + /// Returns a random element from the `Array`. + /// + /// - Returns: A random element from the array or `nil` if empty. + public var sample: Element? { + guard let randomIndex = Int(randomBelow: count) else { return nil } + return self[randomIndex] + } + + /// Returns a given number of random elements from the `Array`. + /// + /// - Parameters: + /// - size: The number of random elements wanted. + /// - Returns: An array with the given number of random elements or `nil` if empty. + public func sample(size: Int) -> [Element]? { + guard !isEmpty else { return nil } + + var sampleElements: [Element] = [] + size.times { sampleElements.append(sample!) } + + return sampleElements + } +} + +extension Sequence where Element: Numeric { + /// Returns the sum of all elements. + public func sum() -> Element { + return reduce(0, +) + } +} + +extension Collection where Element == Int { + /// Returns the average of all elements as a Double value. + public func average() -> Double { + return reduce(0) { $0 + Double($1) } / Double(count) + } +} + +extension Collection where Element == Double { + /// Returns the average of all elements as a Double value. + public func average() -> Double { + return reduce(0, +) / Double(count) + } +} + extension Array where Element: Comparable { /// Sorts the collection in place by the order specified in the closure. /// diff --git a/Frameworks/HandySwift/Extensions/NSRangeExtension.swift b/Frameworks/HandySwift/Extensions/NSRangeExtension.swift new file mode 100644 index 0000000..e9744d6 --- /dev/null +++ b/Frameworks/HandySwift/Extensions/NSRangeExtension.swift @@ -0,0 +1,15 @@ +// +// Created by Cihat GΓΌndΓΌz on 11.02.19. +// Copyright Β© 2019 Flinesoft. All rights reserved. +// + +import Foundation + +extension NSRange { + /// Initializes an NSRange from a Swift String.Range when the String is provided. + public init(_ range: Range, in string: String) { + self.init() + self.location = string.utf16.distance(from: string.startIndex, to: range.lowerBound) + self.length = string.utf16.distance(from: range.lowerBound, to: range.upperBound) + } +} diff --git a/Frameworks/HandySwift/Extensions/StringExtension.swift b/Frameworks/HandySwift/Extensions/StringExtension.swift index 9d0fe47..2b26a1e 100644 --- a/Frameworks/HandySwift/Extensions/StringExtension.swift +++ b/Frameworks/HandySwift/Extensions/StringExtension.swift @@ -16,6 +16,16 @@ extension String { return isEmpty ? nil : self[index(startIndex, offsetBy: Int(randomBelow: count)!)] } + /// Returns the range containing the full String. + public var fullRange: Range { + return startIndex ..< endIndex + } + + /// Returns the range as NSRange type for the full String. + public var fullNSRange: NSRange { + return NSRange(fullRange, in: self) + } + /// Create new instance with random numeric/alphabetic/alphanumeric String of given length. /// /// - Parameters: diff --git a/Frameworks/HandySwift/Structs/SortedArray.swift b/Frameworks/HandySwift/Structs/SortedArray.swift index 30a4c10..8ef624a 100644 --- a/Frameworks/HandySwift/Structs/SortedArray.swift +++ b/Frameworks/HandySwift/Structs/SortedArray.swift @@ -49,8 +49,10 @@ public struct SortedArray { public func index(where predicate: (Element) -> Bool) -> Int? { // cover trivial cases guard !array.isEmpty else { return nil } + // swiftlint:disable all if let first = array.first, predicate(first) { return array.startIndex } if let last = array.last, !predicate(last) { return nil } + // swiftlint:enable all // binary search for first matching element var foundMatch = false diff --git a/Frameworks/SupportingFiles/Info.plist b/Frameworks/SupportingFiles/Info.plist index 111577c..561d538 100644 --- a/Frameworks/SupportingFiles/Info.plist +++ b/Frameworks/SupportingFiles/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 2.7.1 + 2.8.0 CFBundleSignature ???? diff --git a/HandySwift.podspec b/HandySwift.podspec index b717f75..9d9dfdb 100644 --- a/HandySwift.podspec +++ b/HandySwift.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "HandySwift" - s.version = "2.7.1 + s.version = "2.8.0 " s.summary = "Handy Swift features that didn't make it into the Swift standard library" diff --git a/HandySwift.xcodeproj/project.pbxproj b/HandySwift.xcodeproj/project.pbxproj index 249b5a6..fd7e324 100644 --- a/HandySwift.xcodeproj/project.pbxproj +++ b/HandySwift.xcodeproj/project.pbxproj @@ -11,6 +11,12 @@ 3F95C8D520F22DEE0045AFD0 /* CollectionExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F95C8D320F22DC60045AFD0 /* CollectionExtensionTests.swift */; }; 3F95C8D620F22DEF0045AFD0 /* CollectionExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F95C8D320F22DC60045AFD0 /* CollectionExtensionTests.swift */; }; 3F95C8D720F22DEF0045AFD0 /* CollectionExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F95C8D320F22DC60045AFD0 /* CollectionExtensionTests.swift */; }; + 8218E4D62211D193007AAAF3 /* NSRangeExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8218E4D52211D193007AAAF3 /* NSRangeExtension.swift */; }; + 8218E4D72211D193007AAAF3 /* NSRangeExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8218E4D52211D193007AAAF3 /* NSRangeExtension.swift */; }; + 8218E4D82211D193007AAAF3 /* NSRangeExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8218E4D52211D193007AAAF3 /* NSRangeExtension.swift */; }; + 8218E4DA2211D270007AAAF3 /* NSRangeExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8218E4D92211D270007AAAF3 /* NSRangeExtensionTests.swift */; }; + 8218E4DB2211D270007AAAF3 /* NSRangeExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8218E4D92211D270007AAAF3 /* NSRangeExtensionTests.swift */; }; + 8218E4DC2211D270007AAAF3 /* NSRangeExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8218E4D92211D270007AAAF3 /* NSRangeExtensionTests.swift */; }; 823B2B351C24AAB7007B3CDD /* HandySwift.h in Headers */ = {isa = PBXBuildFile; fileRef = 823B2B341C24AAB7007B3CDD /* HandySwift.h */; settings = {ATTRIBUTES = (Public, ); }; }; 823B2B3C1C24AAB7007B3CDD /* HandySwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 823B2B311C24AAB6007B3CDD /* HandySwift.framework */; }; 823B2B4D1C24ABA4007B3CDD /* IntExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 823B2B4C1C24ABA4007B3CDD /* IntExtension.swift */; }; @@ -114,6 +120,11 @@ /* Begin PBXFileReference section */ 3F95C8D120F22A3C0045AFD0 /* CollectionExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionExtension.swift; sourceTree = ""; }; 3F95C8D320F22DC60045AFD0 /* CollectionExtensionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionExtensionTests.swift; sourceTree = ""; }; + 8218E4D52211D193007AAAF3 /* NSRangeExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSRangeExtension.swift; sourceTree = ""; }; + 8218E4D92211D270007AAAF3 /* NSRangeExtensionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSRangeExtensionTests.swift; sourceTree = ""; }; + 8218E4DD2211D7D3007AAAF3 /* CODE_OF_CONDUCT.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CODE_OF_CONDUCT.md; sourceTree = ""; }; + 8218E4DE2211D7D3007AAAF3 /* CHANGELOG.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CHANGELOG.md; sourceTree = ""; }; + 8218E4DF2211D7D3007AAAF3 /* CONTRIBUTING.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CONTRIBUTING.md; sourceTree = ""; }; 823B2B311C24AAB6007B3CDD /* HandySwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = HandySwift.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 823B2B341C24AAB7007B3CDD /* HandySwift.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HandySwift.h; sourceTree = ""; }; 823B2B361C24AAB7007B3CDD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -138,7 +149,6 @@ 82CAE2931C2ED5E000F934A7 /* StringExtensionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringExtensionTests.swift; sourceTree = ""; }; 82CAE2951C2EE64900F934A7 /* ArrayExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayExtension.swift; sourceTree = ""; }; 82CAE2971C2EE95200F934A7 /* ArrayExtensionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ArrayExtensionTests.swift; sourceTree = ""; }; - 82EB7874215B96C70042E0FD /* .projlint.yml */ = {isa = PBXFileReference; lastKnownFileType = text; path = .projlint.yml; sourceTree = ""; }; 82EB7875215B96E20042E0FD /* beak.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = beak.swift; sourceTree = ""; }; 82EB7876215B98530042E0FD /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; 82F22E551C26434900E784A2 /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; }; @@ -254,6 +264,7 @@ 8280D7DB1C4A6EC9001172EF /* DictionaryExtension.swift */, A1F221631E3CC05100419B06 /* DispatchTimeIntervalExtension.swift */, 823B2B4C1C24ABA4007B3CDD /* IntExtension.swift */, + 8218E4D52211D193007AAAF3 /* NSRangeExtension.swift */, 82CAE2911C2ED1A200F934A7 /* StringExtension.swift */, A11830D21E589F6700CBE087 /* TimeIntervalExtension.swift */, ); @@ -268,6 +279,7 @@ 8280D7DF1C4A6FF3001172EF /* DictionaryExtensionTests.swift */, 827599631E520FB800787F99 /* DispatchTimeIntervalExtensionTests.swift */, 823B2B4F1C24AC00007B3CDD /* IntExtensionTests.swift */, + 8218E4D92211D270007AAAF3 /* NSRangeExtensionTests.swift */, 82CAE2931C2ED5E000F934A7 /* StringExtensionTests.swift */, A11830D61E58A11D00CBE087 /* TimeIntervalExtensionTests.swift */, ); @@ -334,9 +346,11 @@ A1F5AEEA1E05700F003D6949 /* RootFiles */ = { isa = PBXGroup; children = ( - 82EB7874215B96C70042E0FD /* .projlint.yml */, A15C62221EE734F100A7CA38 /* .swiftlint.yml */, 82EB7875215B96E20042E0FD /* beak.swift */, + 8218E4DE2211D7D3007AAAF3 /* CHANGELOG.md */, + 8218E4DD2211D7D3007AAAF3 /* CODE_OF_CONDUCT.md */, + 8218E4DF2211D7D3007AAAF3 /* CONTRIBUTING.md */, A19DD6921DE2B70F00C66584 /* HandySwift.podspec */, 82EB7876215B98530042E0FD /* LICENSE */, 82F22E551C26434900E784A2 /* Package.swift */, @@ -384,7 +398,6 @@ 823B2B2E1C24AAB6007B3CDD /* Headers */, 823B2B2F1C24AAB6007B3CDD /* Resources */, 82F967F41C67A68A0003F12A /* SwiftLint */, - 82EB7873215B92E90042E0FD /* ProjLint */, ); buildRules = ( ); @@ -422,7 +435,6 @@ 825EFDC71C3333B000558497 /* Headers */, 825EFDC81C3333B000558497 /* Resources */, 82F967F51C67A69A0003F12A /* SwiftLint */, - 82EB7878215B9EE30042E0FD /* ProjLint */, ); buildRules = ( ); @@ -460,7 +472,6 @@ 825EFDE61C33351200558497 /* Headers */, 825EFDE71C33351200558497 /* Resources */, 82F967F61C67A6A80003F12A /* SwiftLint */, - 82EB7879215B9EF10042E0FD /* ProjLint */, ); buildRules = ( ); @@ -593,60 +604,6 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 82EB7873215B92E90042E0FD /* ProjLint */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - ); - name = ProjLint; - outputFileListPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "if [ \"${CONFIGURATION}\" = \"Debug\" ]; then\n if which projlint > /dev/null; then\n projlint lint --xcode --timeout 2 --ignore-network-errors\n else\n echo \"warning: ProjLint not installed, download it from https://github.com/JamitLabs/ProjLint\"\n fi\nfi\n"; - }; - 82EB7878215B9EE30042E0FD /* ProjLint */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - ); - name = ProjLint; - outputFileListPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "if [ \"${CONFIGURATION}\" = \"Debug\" ]; then\n if which projlint > /dev/null; then\n projlint lint --xcode --timeout 2 --ignore-network-errors\n else\n echo \"warning: ProjLint not installed, download it from https://github.com/JamitLabs/ProjLint\"\n fi\nfi\n"; - }; - 82EB7879215B9EF10042E0FD /* ProjLint */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - ); - name = ProjLint; - outputFileListPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "if [ \"${CONFIGURATION}\" = \"Debug\" ]; then\n if which projlint > /dev/null; then\n projlint lint --xcode --timeout 2 --ignore-network-errors\n else\n echo \"warning: ProjLint not installed, download it from https://github.com/JamitLabs/ProjLint\"\n fi\nfi\n"; - }; 82F967F41C67A68A0003F12A /* SwiftLint */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -700,6 +657,7 @@ CC120CC2205FDB9300C37D7C /* Regex.swift in Sources */, 826F69AC1C3895A300B2CC6B /* FrequencyTable.swift in Sources */, A1F221641E3CC05100419B06 /* DispatchTimeIntervalExtension.swift in Sources */, + 8218E4D62211D193007AAAF3 /* NSRangeExtension.swift in Sources */, 3F95C8D220F22A3C0045AFD0 /* CollectionExtension.swift in Sources */, 823B2B4D1C24ABA4007B3CDD /* IntExtension.swift in Sources */, C5C89B9420B0A0C10048B07C /* Weak.swift in Sources */, @@ -724,6 +682,7 @@ 82CAE2941C2ED5E000F934A7 /* StringExtensionTests.swift in Sources */, 82CAE2981C2EE95200F934A7 /* ArrayExtensionTests.swift in Sources */, 82812A9F1D06926800CD5B6C /* GlobalsTests.swift in Sources */, + 8218E4DA2211D270007AAAF3 /* NSRangeExtensionTests.swift in Sources */, 8280D7E01C4A6FF3001172EF /* DictionaryExtensionTests.swift in Sources */, 3F95C8D520F22DEE0045AFD0 /* CollectionExtensionTests.swift in Sources */, CC4AE0CF2087D8A7009931F6 /* RegexTests.swift in Sources */, @@ -738,6 +697,7 @@ CC120CC3205FDC4C00C37D7C /* Regex.swift in Sources */, C5CFB6AD20B0A70300830511 /* Unowned.swift in Sources */, 826F69AD1C3895A300B2CC6B /* FrequencyTable.swift in Sources */, + 8218E4D72211D193007AAAF3 /* NSRangeExtension.swift in Sources */, 825EFE051C33358400558497 /* StringExtension.swift in Sources */, 82E21E8E211AF9960061EB1B /* CollectionExtension.swift in Sources */, C5CFB6AF20B0A78F00830511 /* Weak.swift in Sources */, @@ -762,6 +722,7 @@ 825EFE121C3335A400558497 /* ArrayExtensionTests.swift in Sources */, 825EFE0F1C3335A400558497 /* IntExtensionTests.swift in Sources */, 82812AA01D06926800CD5B6C /* GlobalsTests.swift in Sources */, + 8218E4DB2211D270007AAAF3 /* NSRangeExtensionTests.swift in Sources */, 8280D7E11C4A6FF3001172EF /* DictionaryExtensionTests.swift in Sources */, 3F95C8D620F22DEF0045AFD0 /* CollectionExtensionTests.swift in Sources */, CC4AE0D02087D8A8009931F6 /* RegexTests.swift in Sources */, @@ -776,6 +737,7 @@ CC120CC4205FDC4D00C37D7C /* Regex.swift in Sources */, C5CFB6AE20B0A70300830511 /* Unowned.swift in Sources */, 826F69AE1C3895A300B2CC6B /* FrequencyTable.swift in Sources */, + 8218E4D82211D193007AAAF3 /* NSRangeExtension.swift in Sources */, 825EFE0B1C33358500558497 /* StringExtension.swift in Sources */, 82E21E8F211AF9970061EB1B /* CollectionExtension.swift in Sources */, C5CFB6B020B0A79000830511 /* Weak.swift in Sources */, @@ -800,6 +762,7 @@ 825EFE181C3335A500558497 /* ArrayExtensionTests.swift in Sources */, 825EFE151C3335A500558497 /* IntExtensionTests.swift in Sources */, 82812AA11D06926800CD5B6C /* GlobalsTests.swift in Sources */, + 8218E4DC2211D270007AAAF3 /* NSRangeExtensionTests.swift in Sources */, 8280D7E21C4A6FF3001172EF /* DictionaryExtensionTests.swift in Sources */, 3F95C8D720F22DEF0045AFD0 /* CollectionExtensionTests.swift in Sources */, CC4AE0D12087D8A9009931F6 /* RegexTests.swift in Sources */, diff --git a/README.md b/README.md index a40ca06..3abe2e3 100644 --- a/README.md +++ b/README.md @@ -13,9 +13,9 @@ alt="Codebeat Status"> - Version: 2.7.1
+             alt= "!🍏🐲✈️🎎🐲🍜??🍜" ``` +#### .fullRange + +Get the full `Range` on a `String` object. + +``` Swift +let unicodeString = "Hello composed unicode symbols! πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘¦πŸ‘¨β€πŸ‘¨β€πŸ‘¦β€πŸ‘¦πŸ‘©β€πŸ‘©β€πŸ‘§β€πŸ‘§" +unicodeString[unicodeString.fullRange] // => same string +``` + +### NSRangeExtension + +#### init(_:in:) + +Converting from `NSRange` to `Range` became simple in Swift 4: + +``` Swift +let string = "Hello World!" +let nsRange = NSRange(location: 0, length: 10) +let swiftRange = Range(nsRange, in: string) +``` + +The opposite is now also possible with this extension: + +``` Swift +let string = "Hello World!" +let swiftRange: Range = string.fullRange +let nsRange = NSRange(swiftRange, in: string) +``` + ### ArrayExtension #### .sample diff --git a/Tests/HandySwiftTests/Extensions/ArrayExtensionTests.swift b/Tests/HandySwiftTests/Extensions/ArrayExtensionTests.swift index 3f491ec..a6998b5 100644 --- a/Tests/HandySwiftTests/Extensions/ArrayExtensionTests.swift +++ b/Tests/HandySwiftTests/Extensions/ArrayExtensionTests.swift @@ -73,4 +73,20 @@ class ArrayExtensionTests: XCTestCase { XCTAssertEqual(testArray[index], sortedArray[index]) } } + + func testSum() { + let intArray = [1, 2, 3, 4, 5] + XCTAssertEqual(intArray.sum(), 15) + + let doubleArray = [1.0, 2.0, 3.0, 4.0, 5.0] + XCTAssertEqual(doubleArray.sum(), 15.0, accuracy: 0.001) + } + + func testAverage() { + let intArray = [1, 2, 10] + XCTAssertEqual(intArray.average(), 4.333, accuracy: 0.001) + + let doubleArray = [1.0, 2.0, 10.0] + XCTAssertEqual(doubleArray.average(), 4.333, accuracy: 0.001) + } } diff --git a/Tests/HandySwiftTests/Extensions/NSRangeExtensionTests.swift b/Tests/HandySwiftTests/Extensions/NSRangeExtensionTests.swift new file mode 100644 index 0000000..d1405d1 --- /dev/null +++ b/Tests/HandySwiftTests/Extensions/NSRangeExtensionTests.swift @@ -0,0 +1,17 @@ +// +// Created by Cihat GΓΌndΓΌz on 11.02.19. +// Copyright Β© 2019 Flinesoft. All rights reserved. +// + +@testable import HandySwift +import XCTest + +class NSRangeExtensionTests: XCTestCase { + func testInitWithSwiftRange() { + let testStrings = ["Simple String", "πŸ‘ͺ πŸ‘¨β€πŸ‘©β€πŸ‘¦ πŸ‘¨β€πŸ‘©β€πŸ‘§ πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘¦ πŸ‘¨β€πŸ‘©β€πŸ‘¦β€πŸ‘¦ πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘§ πŸ‘¨β€πŸ‘¨β€πŸ‘¦ πŸ‘¨β€πŸ‘¨β€πŸ‘§ πŸ‘¨β€πŸ‘¨β€πŸ‘§β€πŸ‘¦ πŸ‘¨β€πŸ‘¨β€πŸ‘¦β€πŸ‘¦ πŸ‘¨β€πŸ‘¨β€πŸ‘§β€πŸ‘§ πŸ‘©β€πŸ‘©β€πŸ‘¦ πŸ‘©β€πŸ‘©β€πŸ‘§ πŸ‘©β€πŸ‘©β€πŸ‘§β€πŸ‘¦ πŸ‘©β€πŸ‘©β€πŸ‘¦β€πŸ‘¦ πŸ‘©β€πŸ‘©β€πŸ‘§β€πŸ‘§"] + + for string in testStrings { + XCTAssertEqual((string as NSString).substring(with: NSRange(string.fullRange, in: string)), string) + } + } +} diff --git a/Tests/HandySwiftTests/Extensions/StringExtensionTests.swift b/Tests/HandySwiftTests/Extensions/StringExtensionTests.swift index 01cc09d..0dffedb 100644 --- a/Tests/HandySwiftTests/Extensions/StringExtensionTests.swift +++ b/Tests/HandySwiftTests/Extensions/StringExtensionTests.swift @@ -44,4 +44,12 @@ class StringExtensionTests: XCTestCase { XCTAssertEqual([1, 2, 3].sample(size: 2)!.count, 2) XCTAssertEqual([1, 2, 3].sample(size: 10)!.count, 10) } + + func testFullRange() { + let testStrings = ["Simple String", "πŸ‘ͺ πŸ‘¨β€πŸ‘©β€πŸ‘¦ πŸ‘¨β€πŸ‘©β€πŸ‘§ πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘¦ πŸ‘¨β€πŸ‘©β€πŸ‘¦β€πŸ‘¦ πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘§ πŸ‘¨β€πŸ‘¨β€πŸ‘¦ πŸ‘¨β€πŸ‘¨β€πŸ‘§ πŸ‘¨β€πŸ‘¨β€πŸ‘§β€πŸ‘¦ πŸ‘¨β€πŸ‘¨β€πŸ‘¦β€πŸ‘¦ πŸ‘¨β€πŸ‘¨β€πŸ‘§β€πŸ‘§ πŸ‘©β€πŸ‘©β€πŸ‘¦ πŸ‘©β€πŸ‘©β€πŸ‘§ πŸ‘©β€πŸ‘©β€πŸ‘§β€πŸ‘¦ πŸ‘©β€πŸ‘©β€πŸ‘¦β€πŸ‘¦ πŸ‘©β€πŸ‘©β€πŸ‘§β€πŸ‘§"] + + for string in testStrings { + XCTAssertEqual(String(string[string.fullRange]), string) + } + } } diff --git a/UsageExamples.playground/Contents.swift b/UsageExamples.playground/Contents.swift index f0634e6..3ab7af0 100644 --- a/UsageExamples.playground/Contents.swift +++ b/UsageExamples.playground/Contents.swift @@ -74,6 +74,20 @@ String(randomWithLength: 6, allowedCharactersType: .alphabetic) String(randomWithLength: 8, allowedCharactersType: .alphaNumeric) String(randomWithLength: 10, allowedCharactersType: .allCharactersIn("?!🐲🍏✈️🎎🍜")) +//: ### .fullRange +//: Get the full `Range` on a `String` object. + +let unicodeString = "Hello composed unicode symbols! πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘¦πŸ‘¨β€πŸ‘¨β€πŸ‘¦β€πŸ‘¦πŸ‘©β€πŸ‘©β€πŸ‘§β€πŸ‘§" +unicodeString[unicodeString.fullRange] + +//: ## NSRangeExtension +//: ### init(_:in:) +//: Adds support for converting `Range` to `NSRange`. + +let swiftRange: Range = unicodeString.fullRange +let nsRange = NSRange(swiftRange, in: unicodeString) +(unicodeString as NSString).substring(with: nsRange) + //: ## Collection Extensions //: ### [try:] //: Returns an element with the specified index and nil if the array does not have that index.