HandySwift
该库的目标是提供一些实用功能,这些功能因为各种原因尚未添加到 Swift 标准库中。这些功能可能是由于 Swift 社区希望保持标准库干净易管理,或者简单地尚未完成对该特定功能的讨论。
如果您喜欢这个库,也可查看 HandyUIKit,它提供了我们认为本来就应该成为 UIKit 框架一部分的实用 UI 功能。
如果您正从 HandySwift 的早期版本升级(例如从 1.x 升级到 2.x),请查看 GitHub 上的发布部分,并查看最后几个主要版本的发布说明(例如 2.0.0),以了解所做的更改概览。这将节省您时间,因为那里包含了有关如何最佳迁移的提示。
安装
目前,推荐通过 Swift Package Manager 安装此库。同时,也支持 Carthage 和 CocoaPods。
当然,您也可以手动将此框架包含到项目中,通过下载它或使用 git 子模块的方式来实现。
使用方法
请查看UsageExamples.playground以获取提供的功能完整列表。为了使其正常工作,请在.xcworkspace
内部打开Playground。
功能概述
- 全局变量
- 扩展
- 新类型
全局变量
一些全局辅助工具。
delay(bySeconds:) { ... }
延迟运行给定的闭包,延迟时间以秒为单位。可以选项目 Dispatch队列,默认为主线程。
delay(by: .milliseconds(1_500)) { // Runs in Main thread by default
date = NSDate() // Delayed by 1.5 seconds: 2016-06-07 05:38:05 +0000
}
delay(by: .seconds(5), dispatchLevel: .userInteractive) {
date = NSDate() // Delayed by 5 seconds: 2016-06-07 05:38:08 +0000
}
Int扩展
init(randomBelow:)
初始化随机 Int 值,值小于给定的积极数值。
Int(randomBelow: 50)! // => 26
Int(randomBelow: 1_000_000)! // => 208041
.times
重复执行指定次数的代码块。
3.times { print("Hello World!") }
// => prints "Hello World!" 3 times
.timesMake
通过多次添加闭包的返回值来创建数组。
let intArray = 5.timesMake { Int(randomBelow: 1_000)! }
// => [481, 16, 680, 87, 912]
ComparableExtension
clamped(to:)
将限制范围作为 Comparable
的边界。支持 ClosedRange
(a ... b
), PartialRangeFrom
(a...
) 和 PartialRangeThrough
(...b
) 作为 limits
。
let myNum = 3
myNum.clamped(to: 0 ... 6) // => 3
myNum.clamped(to: 0 ... 2) // => 2
myNum.clamped(to: 4 ... 6) // => 4
myNum.clamped(to: 5...) // => 4
myNum.clamped(to: ...2) // => 2
let myString = "d"
myString.clamped(to: "a" ... "g") // => "d"
myString.clamped(to: "a" ... "c") // => "c"
myString.clamped(to: "e" ... "g") // => "e"
myString.clamped(to: "f"...) // => "f"
myString.clamped(to: ..."c") // => "c"
clamp(to:)
与 clamped(to:)
相同的 in-place mutating
变体。
var myNum = 3
myNum.clamp(to: 0...2)
myNum // => 2
StringExtension
.stripped()
返回去除前后空白字符的字符串。
" \n\t BB-8 likes Rey \t\n ".stripped()
// => "BB-8 likes Rey"
.isBlank
检查字符串是否包含任何非空白字符。
" \t ".isBlank
// => true
init(randomWithLength:allowedCharactersType:)
获取指定长度的随机数字/字母/字母数字字符串。
String(randomWithLength: 4, allowedCharactersType: .numeric) // => "8503"
String(randomWithLength: 6, allowedCharactersType: .alphabetic) // => "ysTUzU"
String(randomWithLength: 8, allowedCharactersType: .alphaNumeric) // => "2TgM5sUG"
String(randomWithLength: 10, allowedCharactersType: .allCharactersIn("?!🐲🍏✈️🎎🍜"))
// => "!🍏🐲✈️🎎🐲🍜??🍜"
.fullRange
获取字符串对象的完整Range
。
let unicodeString = "Hello composed unicode symbols! 👨👩👧👦👨👨👦👦👩👩👧👧"
unicodeString[unicodeString.fullRange] // => same string
NSRangeExtension
init(_:in:)
在Swift 4中,从NSRange
到Range
的转换变得简单。
let string = "Hello World!"
let nsRange = NSRange(location: 0, length: 10)
let swiftRange = Range(nsRange, in: string)
这个扩展现在也支持反向转换。
let string = "Hello World!"
let swiftRange: Range<String.Index> = string.fullRange
let nsRange = NSRange(swiftRange, in: string)
ArrayExtension
.sample
返回数组中的一个随机元素,如果数组为空则返回nil。
[1, 2, 3, 4, 5].sample // => 4
([] as [Int]).sample // => nil
.sample(size:)
返回一个包含size
个随机元素的新数组,如果数组为空则返回nil。
[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
.combinations(with:)
将每个元素与给定数组的每个元素组合。
[1, 2, 3].combinations(with: ["A", "B"])
// => [(1, "A"), (1, "B"), (2, "A"), (2, "B"), (3, "A"), (3, "B")]
DictionaryExtension
init?(keys:values:)
初始化一个新的Dictionary
并使用键和值的数组填充它,或者如果数组的计数不同则返回nil。
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
.merge(Dictionary)
将给定的Dictionary
合并到现有Dictionary
中,忽略匹配键的现有值。
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"]
.merged(with: Dictionary)
创建一个新的合并后的Dictionary
,将给定的Dictionary
合并到一个Dictionary
中,并忽略匹配键的现有值。
let immutableDict = ["A": "A value", "B": "Old B value"]
immutableDict.merged(with: ["B": "New B value", "C": "C value"])
// => ["A": "A value", "B": "New B value", "C": "C value"]
DispatchTimeIntervalExtension
.timeInterval
从DispatchTimeInterval
中返回一个TimeInterval
对象。
DispatchTimeInterval.milliseconds(500).timeInterval // => 0.5
TimeIntervalExtension
基于单位的伪初始化器
返回一个带有指定单位给定值的TimeInterval
对象。
TimeInterval.days(1.5) // => 129600
TimeInterval.hours(1.5) // => 5400
TimeInterval.minutes(1.5) // => 90
TimeInterval.seconds(1.5) // => 1.5
TimeInterval.milliseconds(1.5) // => 0.0015
TimeInterval.microseconds(1.5) // => 1.5e-06
TimeInterval.nanoseconds(1.5) // => 1.5e-09
基于单位的获取器
返回将时间间隔转换为指定单位后的双精度值。
let timeInterval: TimeInterval = 60 * 60 * 6
timeInterval.days // => 0.25
timeInterval.hours // => 6
timeInterval.minutes // => 360
timeInterval.seconds // => 21600
timeInterval.milliseconds // => 21600000
timeInterval.microseconds // => 21600000000
timeInterval.nanoseconds // => 21600000000000
SortedArray
此包装器的核心目的是提供对排序数组的特定操作的速度提升。
初始化数组(init(array:)) & .array
let unsortedArray = [5, 2, 1, 3, 0, 4]
let sortedArray = SortedArray(unsortedArray)
sortedArray.array // => [0, 1, 2, 3, 4, 5]
.index
使用二分查找查找给定谓词匹配的最小子标以提高性能(O(log n)
)。
SortedArray([5, 2, 1, 3, 0, 4]).index { $0 > 1 }
// => 2
.prefix(upTo:) / .prefix(through:)
SortedArray([5, 2, 1, 3, 0, 4]).prefix(upTo: 2)
// => [0, 1]
.suffix(from:)
SortedArray([5, 2, 1, 3, 0, 4]).suffix(from: 2)
// => [2, 3, 4, 5]
频率表(FrequencyTable)
使用values和闭包初始化 FrequencyTable(values: valuesArray) { valueToFrequencyClosure }
使用值和闭包初始化。
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>
.sample
返回数组中的随机元素,其出现次数的概率为基础,如果数组为空则返回nil。
frequencyTable.sample
let randomWord = frequencyTable.sample.map { $0.word }
// => "Harry"
.sample(size:)
返回包含 size
个基于出现次数的概率随机元素的数组,如果数组为空则返回nil。
frequencyTable.sample(size: 6)
let randomWords = frequencyTable.sample(size: 6)!.map { $0.word }
// => ["Harry", "Ronald", "Harry", "Harry", "Hermione", "Hermione"]
正则表达式
正则表达式
是基于 NSRegularExpression
API 构建的一个 swifty 正则表达式引擎。
init(_:options:)
使用模式以及可选的选项进行初始化。
let regex = try Regex("(Phil|John), [\\d]{4}")
let options: Regex.Options = [.ignoreCase, .anchorsMatchLines, .dotMatchesLineSeparators, .ignoreMetacharacters]
let regexWithOptions = try Regex("(Phil|John), [\\d]{4}", options: options)
regex.matches(_:)
检查正则表达式是否与字符串匹配
regex.matches("Phil, 1991") // => true
regex.matches(in:)
返回所有匹配项
regex.matches(in: "Phil, 1991 and John, 1985")
// => [Match<"Phil, 1991">, Match<"John, 1985">]
regex.firstMatch(in:)
如果有匹配项,则返回第一个匹配项
regex.firstMatch(in: "Phil, 1991 and John, 1985")
// => Match<"Phil, 1991">
regex.replacingMatches(in:with:count:)
用模板字符串替换字符串中的所有匹配项,最多替换(count)个匹配项。
regex.replacingMatches(in: "Phil, 1991 and John, 1985", with: "$1 was born in $2", count: 2)
// => "Phil was born in 1991 and John was born in 1985"
match.string
返回捕获的字符串
match.string // => "Phil, 1991"
match.range
返回捕获字符串在基本字符串中的范围
match.range // => Range
match.captures
返回匹配项的捕获组
match.captures // => ["Phil", "1991"]
match.string(applyingTemplate:)
用模板字符串替换匹配的字符串
match.string(applyingTemplate: "$1 was born in $2")
// => "Phil was born in 1991"
Weak
Weak
是用于存储Wrapped
实例弱引用的包装器。
Weak(_:)
使用对象引用初始化。
let text: NSString = "Hello World!"
var weak = Weak(text)
访问内部引用
使用 value
属性访问内部包装后的引用。
print(weak.value!)
可表示空值协议符合
通过赋值为 nil 创建 Weak
包装器。
var weakWrappedValue: Weak<AnyObject> = nil
非拥有
非拥有
是用于存储对 Wrapped
实例非拥有引用的包装器。
非拥有(_:)
使用对象引用初始化。
var unowned = Unowned(text)
访问内部引用
使用 value
属性访问内部包装后的引用。
print(unowned.value)
CollectionExtension
[try:]
返回指定索引的元素,如果元素不存在则返回 nil。
let testArray = [0, 1, 2, 3, 20]
testArray[try: 4] // => Optional(20)
testArray[try: 20] // => nil
.sum()
返回所有元素的求和。返回类型由数值元素决定,例如对于[int]是int。注意:仅对Numberic
类型的元素有效。
[0, 1, 2, 3, 4].sum() // => 10
[0.5, 1.5, 2.5].sum() // => 4.5
.average()
以Double类型返回所有元素的平均值。注意:仅对 Int 和 Double 类型的集合有效。
[10, 20, 30, 40].average() // => 25.0
[10.75, 20.75, 30.25, 40.25].average() // => 25.5
Withable
简单协议,使得具有多个属性的构造和修改对象更加高效(函数式、链式、箭头式)。默认支持所有的 NSObject
子类。
struct Foo: Withable {
var bar: Int
var isEasy: Bool = false
}
let defaultFoo = Foo(bar: 5)
let customFoo = Foo(bar: 5).with { $0.isEasy = true }
foo.isEasy // => false
foo2.isEasy // => true
Donation
BartyCrouch 由 Cihat Gündüz 在空闲时间开发。如果您想感谢我并支持这个项目的开发,请 在 PayPal(https://paypal.me/Dschee/5EUR)上做一小笔捐赠。如果您也喜欢我的其他 开源贡献 和 文章,请考虑通过 成为 GitHub(https://github.com/sponsors/Jeehut)上的赞助者 或 Patreon(https://www.patreon.com/Jeehut)上的支持者 来激励我。
非常感谢您提供的任何捐赠,这真的帮助很大!
捐赠
欢迎捐赠。您可以在GitHub上提交一个包含您想法的问题,或者自己实现一个想法并提交拉取请求。如果您想贡献代码,请确保在您的commit messages
中遵循相同的语法和语义(见此处的说明)。同时,请确保在代码提交介绍中添加一个条目,解释您所做的更改。
许可协议
本库采用MIT 许可协议发布。查看LICENSE文件以了解详细信息。