HandySwift 3.2.1

HandySwift 3.2.1

测试已测试
语言语言 SwiftSwift
许可证 MIT
发布最后发布2020年10月
SPM支持 SPM

Cihat Gündüz 维护。



CI Coverage Version: 3.2.1 Swift: 5.1 Platforms: iOS | tvOS | macOS | Linux License: MIT
PayPal: Donate GitHub: Become a sponsor Patreon: Become a patron

安装使用捐赠问题贡献许可证

HandySwift

该库的目标是提供一些实用功能,这些功能因为各种原因尚未添加到 Swift 标准库中。这些功能可能是由于 Swift 社区希望保持标准库干净易管理,或者简单地尚未完成对该特定功能的讨论。

如果您喜欢这个库,也可查看 HandyUIKit,它提供了我们认为本来就应该成为 UIKit 框架一部分的实用 UI 功能。

如果您正从 HandySwift 的早期版本升级(例如从 1.x 升级到 2.x),请查看 GitHub 上的发布部分,并查看最后几个主要版本的发布说明(例如 2.0.0),以了解所做的更改概览。这将节省您时间,因为那里包含了有关如何最佳迁移的提示。

安装

目前,推荐通过 Swift Package Manager 安装此库。同时,也支持 CarthageCocoaPods

当然,您也可以手动将此框架包含到项目中,通过下载它或使用 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中,从NSRangeRange的转换变得简单。

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文件以了解详细信息。