Installation • Usage • Issues • Contributing • License
The goal of this library is to provide handy features that didn't make it to the Swift standard library (yet) due to many different reasons. Those could be that the Swift community wants to keep the standard library clean and manageable or simply hasn't finished discussion on a specific feature yet.
Currently the recommended way of installing this library is via Carthage. Cocoapods is supported, too. Swift Package Manager was targeted but didn't work in my tests.
You can of course also just include this framework manually into your project by downloading it or by using git submodules.
Depending on the Swift version of your project, place one of the following lines to your Cartfile:
Swift 3:
github "Flinesoft/HandySwift"
Swift 2.3:
github "Flinesoft/HandySwift" "support/swift2.3"
Swift 2.2:
github "Flinesoft/HandySwift" == 1.2.0
Now run carthage update
. Then drag & drop the HandySwift.framework in the Carthage/build folder to your project. Now you can import HandySwift
in each class you want to use its features. Refer to the Carthage README for detailed / updated instructions.
Add the line pod 'HandySwift'
to your target in your Podfile
and make sure to include use_frameworks!
at the top. The result might look similar to this:
platform :ios, '8.0'
use_frameworks!
target 'MyAppTarget' do
pod 'HandySwift', '~> 1.0'
end
Now close your project and run pod install
from the command line. Then open the .xcworkspace
from within your project folder.
Build your project once (with Cmd+B
) to update the frameworks known to Xcode. Now you can import HandySwift
in each class you want to use its features.
Refer to CocoaPods.org for detailed / updates instructions.
Please have a look at the UsageExamples.playground for a complete list of features provided.
Open the Playground from within the .xcworkspace
in order for it to work.
Some global helpers.
Runs a given closure after a delay given in seconds. Dispatch queue can be set optionally, defaults to Main thread.
var date = NSDate() // Without delay: 2016-06-07 05:38:03 +0000
delay(bySeconds: 1.5) { // Runs in Main thread by default
date = NSDate() // Delayed by 1.5 seconds: 2016-06-07 05:38:05 +0000
}
delay(bySeconds: 5, dispatchLevel: .userInteractive) {
date = NSDate() // Delayed by 5 seconds: 2016-06-07 05:38:08 +0000
}
Initialize random Int value below given positive value.
Int(randomBelow: 50) // => 26
Int(randomBelow: 1_000_000) // => 208041
Repeat some code block a given number of times.
3.times{ array.append("Hello World!") }
// => ["Hello World!", "Hello World!", "Hello World!"]
5.times {
let randomInt = Int(randomBelow: 1_000)
intArray.append(randomInt)
}
// => [481, 16, 680, 87, 912]
Returns string with whitespace characters stripped from start and end.
" \t BB-8 likes Rey \t ".strip
// => "BB-8 likes Rey"
Checks if String contains any characters other than whitespace characters.
" \t ".isBlank
// => true
Get random numeric/alphabetic/alphanumeric String of given length.
String(randomWithLength: 4, allowedCharactersType: .numeric) // => "8503"
String(randomWithLength: 6, allowedCharactersType: .alphabetic) // => "ysTUzU"
String(randomWithLength: 8, allowedCharactersType: .alphaNumeric) // => "2TgM5sUG"
String(randomWithLength: 10, allowedCharactersType: .allCharactersIn("?!🐲🍏✈️🎎🍜"))
// => "!🍏🐲✈️🎎🐲🍜??🍜"
Returns a random element within the array or nil if array empty.
[1, 2, 3, 4, 5].sample() // => 4
([] as [Int]).sample() // => nil
Returns an array with size
random elements or nil if array empty.
[1, 2, 3, 4, 5].sample(size: 3) // => [2, 1, 4]
[1, 2, 3, 4, 5].sample(size: 8) // => [1, 4, 2, 4, 3, 4, 1, 5]
([] as [Int]).sample(size: 3) // => nil
Initializes a new Dictionary
and fills it with keys and values arrays or returns nil if count of arrays differ.
let structure = ["firstName", "lastName"]
let dataEntries = [["Harry", "Potter"], ["Hermione", "Granger"], ["Ron", "Weasley"]]
Dictionary(keys: structure, values: dataEntries[0]) // => ["firstName": "Harry", "lastName": "Potter"]
dataEntries.map{ Dictionary(keys: structure, values: $0) }
// => [["firstName": "Harry", "lastName": "Potter"], ["firstName": "Hermione", "lastName": "Grange"], ...]
Dictionary(keys: [1,2,3], values: [1,2,3,4,5]) // => nil
Merges a given Dictionary
into an existing Dictionary
overriding existing values for matching keys.
var dict = ["A": "A value", "B": "Old B value"]
dict.merge(["B": "New B value", "C": "C value"])
dict // => ["A": "A value", "B": "New B value", "C": "C value"]
Create new merged Dictionary
with the given Dictionary
merged into a Dictionary
overriding existing values for matching keys.
let immutableDict = ["A": "A value", "B": "Old B value"]
immutableDict.mergedWith(["B": "New B value", "C": "C value"])
// => ["A": "A value", "B": "New B value", "C": "C value"]
Returns a tuple with named RGBA parameters for easy access.
let rgbaColor = UIColor(red: 0.1, green: 0.2, blue: 0.3, alpha: 0.4)
rgbaColor.rgba.red // => 0.1
rgbaColor.rgba.green // => 0.2
rgbaColor.rgba.blue // => 0.3
rgbaColor.rgba.alpha // => 0.4
Returns a tuple with named HSBA parameters for easy access.
let hsbaColor = UIColor(hue: 0.1, saturation: 0.2, brightness: 0.3, alpha: 0.4)
hsbaColor.hsba.hue // => 0.1
hsbaColor.hsba.saturation // => 0.2
hsbaColor.hsba.brightness // => 0.3
hsbaColor.hsba.alpha // => 0.4
Creates a new UIColor
object with a single attribute changed by a given difference using addition.
rgbaColor.rgba.blue // => 0.3
let newRgbaColor = rgbaColor.change(.blue, by: 0.2)
newRgbaColor.rgba.blue // => 0.5
Creates a new UIColor
object with the value of a single attribute set to a given value.
hsbaColor.hsba.brightness // => 0.3
let newHsbaColor = hsbaColor.change(.brightness, to: 0.8)
newHsbaColor.hsba.brightness // => 0.8
Returns a new CGSize object with the width and height converted to true pixels on screen.
let size = CGSize(width: 100, height: 50)
size.inPixels // test this with a Retina screen target
// => {w 50 h 25}
size.inPixels(UIScreen.screens.last!) // pass a different screen
// => {w 100 h 50}
Returns a new CGPoint object with the x and y converted to true pixels on screen.
let point = CGPoint(x: 100, y: 50)
point.inPixels // test this with a Retina screen target
// => {x 50 y 25}
let someScreen = UIScreen.screens.last!
point.inPixels(someScreen) // pass a different screen
// => {x 100 y 50}
Returns a new CGRect object with the origin and size converted to true pixels on screen.
let rect = CGRect(x: 10, y: 20, width: 100, height: 50)
rect.inPixels // test this with a Retina screen target
// => {x 5 y 10 w 50 h 25}
let someScreen = UIScreen.screens.last!
rect.inPixels(someScreen) // pass a different screen
// => {x 10 y 20 w 100 h 50}
Creates a new CGRect object from origin zero with given size.
let someSize = CGSize(width: 100, height: 50)
let originZeroRect1 = CGRect(size: someSize)
let originZeroRect2 = CGRect(width: 100, height: 50)
The main purpose of this wrapper is to provide speed improvements for specific actions on sorted arrays.
let unsortedArray = [5, 2, 1, 3, 0, 4]
let sortedArray = SortedArray(array: unsortedArray)
sortedArray.array // => [0, 1, 2, 3, 4, 5]
Finds the lowest index matching the given predicate using binary search for an improved performance (O(log n)
).
SortedArray(array: [5, 2, 1, 3, 0, 4]).firstMatchingIndex{ $0 > 1 }
// => 2
SortedArray(array: [5, 2, 1, 3, 0, 4]).subArray(toIndex: Array<Int>.Index(2))
// => [0, 1]
SortedArray(array: [5, 2, 1, 3, 0, 4]).subArray(fromIndex: Array<Int>.Index(2))
// => [2, 3, 4, 5]
Initialize with values and closure.
struct WordFrequency {
let word: String; let frequency: Int
init(word: String, frequency: Int) { self.word = word; self.frequency = frequency }
}
let wordFrequencies = [
WordFrequency(word: "Harry", frequency: 10),
WordFrequency(word: "Hermione", frequency: 4),
WordFrequency(word: "Ronald", frequency: 1)
]
let frequencyTable = FrequencyTable(values: wordFrequencies){ $0.frequency }
// => HandySwift.FrequencyTable<WordFrequency>
Returns a random element with frequency-based probability within the array or nil if array empty.
frequencyTable.sample()
let randomWord = frequencyTable.sample().map{ $0.word }
// => "Harry"
Returns an array with size
frequency-based random elements or nil if array empty.
frequencyTable.sample(size: 6)
let randomWords = frequencyTable.sample(size: 6)!.map{ $0.word }
// => ["Harry", "Ronald", "Harry", "Harry", "Hermione", "Hermione"]
Contributions are welcome. Please just open an Issue on GitHub to discuss a point or request a feature or send a Pull Request with your suggestion. If there's a related discussion on the Swift Evolution mailing list, please also post the thread name with a link.
Pull requests with new features will only be accepted when the following are given:
- The feature is handy but not (yet) part of the Swift standard library.
- Tests for the new feature exist and all tests pass successfully.
- Usage examples of the new feature are given in the Playgrounds.
Please also try to follow the same syntax and semantic in your commit messages (see rationale here).
This library is released under the MIT License. See LICENSE for details.