SwiftyUtils
SwiftyUtils 将我们需要在每个项目中交付的所有可重用代码分组在一起。此框架包含以下内容
- 扩展
- 协议
- 结构体
- 子类
支持 iOS、macOS、tvOS 和 watchOS,一切都已做到易于使用!
内容
查看仓库以找到每个功能的示例/测试。
Swift、Foundation 和 CoreGraphics 扩展
- 数组
- 包
- CGFloat
- CGPoint
- CGRect
- CGSize
- 颜色
- 日期
- 字典
- 双精度值
- 文件管理器
- 整数
- 通知中心
- NSAttributedString
- NSLayoutConstraint
- NSMutableAttributedString
- NSObject
- NSRange
- 可重用格式化程序
- 字符串
- 定时器
- URL
- UserDefaults
SwiftUI
UIKit 扩展
- UIAlertController
- UIApplication
- UIButton
- UICollectionViewCell
- UIDevice
- UIFont
- UIImage
- UILabel
- UIScreen
- UIStoryboard
- UISwitch
- UITextField
- UITextView
- UIView
- UIViewController
AppKit 扩展
协议
属性包装器
其他
Swift、Foundation和CoreGraphics扩展
数组扩展
安全访问元素
var array = [1, 2, 3]
print(array[safe: 0]) // Optional(1)
print(array[safe: 10]) // nil
查找对象的所有索引
var array = [1, 2, 3, 1]
print(array.indexes(of: 1)) // [0,3]
获取对象首次/最后出现的索引
var array = [1, 2, 3, 1]
print(array.firstIndex(of: 1)) // Optional(0)
print(array.lastIndex(of: 1)) // Optional(3)
移除对象
var array = [1, 2, 3]
myArray.remove(object: 2)
print(myArray) // [1, 3]
myArray.remove(objects: [1, 3])
print(myArray) // []
移除所有重复项
var array = [0, 0, 1, 1, 2]
array.removeDuplicates()
print(array) // [0,1,2]
let array = [0, 0, 1, 1, 2]
let newArray.removedDuplicates()
print(newArray) // [0,1,2]
移除所有实例
var array = [0, 0, 1, 1, 2]
array.removeAll(0)
print(array) // [1,1,2]
let array = [0, 0, 1, 1, 2]
let newArray = array.removedAll(0)
print(newArray) // [1,1,2]
检查数组是否为另一个数组的子集
var array = [1, 2, 3]
print(array.contains([1, 2])) // true
print(array.contains([5])) // false
确定数组是否包含对象
var array = [1, 2, 3]
print(array.contains(1)) // true
print(array.contains(11)) // false
获取两个数组的交集和并集
var myArray = [1, 2, 3]
print(array.intersection(for: [1, 5, 3])) // [1, 3]
print(array.union(values: [5, 6])) // [1, 2, 3, 5, 6]
获取两个数组的差集
var array = [1, 2, 3]
print(array.difference(with: [1])) // [2, 3]
分割成特定大小的块
var array = [1, 2, 3, 4]
print(array.split(intoChunksOf: 2)) // [[1, 2], [3, 4]]
包扩展
获取包信息
Bundle.main.appName
Bundle(url: url)?.appName
Bundle.main.displayName
Bundle(url: url)?.displayName
Bundle.main.appVersion
Bundle(url: url)?.appVersion
Bundle.main.appBuild
Bundle(url: url)?.appBuild
Bundle.main.bundleId
Bundle(url: url)?.bundleId
Bundle.main.schemes
Bundle(url: url)?.schemes
Bundle.main.mainScheme
Bundle(url: url)?.mainScheme
Bundle.main.isInTestFlight
Bundle(url: url)?.isInTestFlight
CGFloat扩展
从Float或Integer创建CGFloat
let imageViewTop = 15.f
CGPoint扩展
添加两个CGPoint
var point1 = CGPoint(x: 10, y: 10)
let point2 = CGPoint(x: 10, y: 10)
print(point1 + point2) // CGPoint(x: 20, y: 20)
point1 += point2
print(point1) // CGPoint(x: 20, y: 20)
减去两个CGPoint
var point1 = CGPoint(x: 10, y: 10)
let point2 = CGPoint(x: 10, y: 10)
print(point1 - point2) // CGPoint(x: 0, y: 0)
point1 -= point2
print(point1) // CGPoint(x: 0, y: 0)
将CGPoint乘以标量
var point1 = CGPoint(x: 10, y: 10)
print(point1 * 2) // CGPoint(x: 20, y: 20)
point1 *= 2
print(point1) // CGPoint(x: 20, y: 20)
CGRect扩展
获取原点的x和y坐标
aRect.x // instead of aRect.origin.x
aRect.y // instead of aRect.origin.y
修改CGRect的一个属性
let rect = CGRect(x: 10, y: 20, width: 30, height: 40)
let widerRect = rect.with(width: 100) // x: 10, y: 20, width: 100, height: 40
let tallerRect = rect.with(height: 100) // x: 10, y: 20, width: 30, height: 100
let rectAtAnotherPosition = rect.with(x: 100).with(y: 200) // x: 100, y: 200, width: 30, height: 40
let rectWithAnotherSize = rect.with(size: CGSize(width: 200, height: 200)) // x: 10, y: 20, width: 200, height: 200
let rectAtYetAnotherPosition = rect.with(origin: CGPoint(x: 100, y: 100)) // x: 100, y: 100, width: 30, height: 40
CGSize 扩展
添加两个 CGSize
var size1 = CGSize(width: 10, height: 10)
let size2 = CGSize(width: 10, height: 10)
print(size1 + size2) // CGSize(width: 20, height: 20)
size1 += size2
print(size1) // CGSize(width: 20, height: 20)
从两个 CGSize
中减去
var size1 = CGSize(width: 10, height: 10)
let size2 = CGSize(width: 10, height: 10)
print(size1 - size2) // CGSize(width: 0, height: 0)
size1 -= size2
print(size1) // CGSize(width: 0, height: 0)
用一个标量乘以一个 CGSize
var size1 = CGSize(x: 10, y: 10)
print(size1 * 2) // CGSize(width: 20, height: 20)
size1 *= 2
print(size1) // CGSize(width: 20, height: 20)
Color 扩展
使用十六进制值创建颜色
let myUIColor = UIColor(hex: "233C64") // Equals 35,60,100,1
let myNSColor = NSColor(hex: "233C64") // Equals 35,60,100,1
访问单个颜色值
let myColor = UIColor(red: 120, green: 205, blue: 44, alpha: 0.3)
print(myColor.redComponent) // 120
print(myColor.greenComponent) // 205
print(myColor.blueComponent) // 44
print(myColor.alpha) // 0.3
获取颜色实例的浅色或深色变体
let color = UIColor(red: 0.5, green: 0.5, blue: 1.0, alpha: 1.0)
let lighter = color.lighter(amount: 0.5)
let darker = color.darker(amount: 0.5)
// OR
let lighter = color.lighter()
let darker = color.darker()
let color = NSColor(red: 0.5, green: 0.5, blue: 1.0, alpha: 1.0)
let lighter = color.lighter(amount: 0.5)
let lighter = color.lighter()
// OR
let darker = color.darker(amount: 0.5)
let darker = color.darker()
Data 扩展
从十六进制字符串初始化
let hexString = "6261736520313020697320736F2062617369632E206261736520313620697320776865726520697427732061742C20796F2E"
let data = Data(hexString: hexString)
从数据获取十六进制字符串
let data = Data(...)
let string = data.toHexString()
// string = "6261736520313020697320736F2062617369632E206261736520313620697320776865726520697427732061742C20796F2E" if using previous example value
从数据获取 UInt8 数组
let data = Data(...)
let array = data.bytesArray
将数据映射到字典
let dictionary = try data.toDictionary()
Date 扩展
从字符串初始化
let format = "yyyy/MM/dd"
let string = "2015/03/11"
print(Date(fromString: string, format: format)) // Optional("2015/03/11 00:00:00 +0000")
将日期转换为字符串
let now = Date()
print(now.string())
print(now.string(dateStyle: .medium, timeStyle: .medium))
print(now.string(format: "yyyy/MM/dd HH:mm:ss"))
查看经过的时间
let now = Date()
let later = Date(timeIntervalSinceNow: -100000)
print(later.days(since: now)) // 1.15740740782409
print(later.hours(since: now)) // 27.7777777733571
print(later.minutes(since: now)) // 1666.66666641732
print(later.seconds(since: now)) // 99999.999984026
检查日期是否在未来或过去
let later = Date(timeIntervalSinceNow: -100000)
print(now.isInFuture) // true
print(now.isInPast) // false
Dictionary 扩展
检查键是否存在于字典中
let dic = ["one": 1, "two": 2]
print(dic.has(key: "one")) // True
print(dic.has(key: "1")) // False
将字典映射到 Data
let data = try dictionary.toData()
轻松获取两个字典的并集
let dic1 = ["one": 1, "two": 2]
let dic2 = ["one": 1, "four": 4]
let dic3 = dic1.union(values: dic2)
print(dic3) // ["one": 1, "two": 2, "four": 4]
映射字典
let dic = ["a": 1, "b": 2, "c": 3]
let result = dic.map { key, value in
return (key.uppercased(), "\(value * 2)")
}
print(dic) // ["A": "2, "B": "4", "C": "6"]
平坦映射字典
let dic = ["a": 1, "b": 2, "c": 3]
let result = dic.flatMap { key, value -> (String, String)? in
if value % 2 == 0 {
return nil
}
return (key.uppercased(), "\(value * 2)")
}
print(dic) // ["A": "2, "C": "6"]
获取两个字典的差集
let dic1 = ["one": 1, "two": 2]
let dic2 = ["one": 1, "four": 4]
difference(with: dic1, dic2) // ["two": 2, "four": 4]
合并多个字典
let dic1 = ["one": 1, "two": 2]
let dic2 = ["three": 3, "four": 4]
var finalDic = [String: Int]()
finalDic.merge(with: dic1, dic2)
print(finalDic) // ["one": 1, "two": 2, "three": 3, "four": 4]
双层扩展
获取以毫秒、秒、小时或天为时间间隔
print(1.second) // 1
print(1.minute) // 60
print(1.hour) // 3600
print(1.2.seconds) // 1.2
print(1.5.minutes) // 90.0
print(1.5.hours) // 5400.0
print(1.3.milliseconds) // 0.0013
print(0.5.day) // 43200
print(1.day) // 86400
print(2.day) // 172800
按区域设置格式化货币值
print(Double(3.24).formattedPrice) // "$3.24"
print(Double(10).formattedPrice) // "$10.00"
文件管理器扩展
按规定操作系统获取文档目录URL
FileManager.document
// OR
FileManager.default.document
创建新目录
FileManager.createDirectory(at: directoryUrl)
// OR
FileManager.default.createDirectory(at: directoryUrl)
删除临时目录内容
FileManager.removeTemporaryFiles()
// OR
FileManager.default.removeTemporaryFiles()
删除文档目录内容
FileManager.removeDocumentFiles()
// OR
FileManager.default.removeDocumentFiles()
整型扩展
var myNumber = -33
print(myNumber.isEven) // false
print(myNumber.isOdd) // true
print(myNumber.isPositive) // false
print(myNumber.isNegative) // true
print(myNumber.digits) // 2
四舍五入到最接近的值/向下舍入/向上舍入
var value = 17572
print(value.nearestDozens) // 17570
print(value.nearestHundreds) // 17600
print(value.nearestThousands) // 18000
print(value.nearest(to: 1000) // 18000
value = 17578
print(value.nearestBelowDozens) // 17570
print(value.nearestBelowHundreds) // 17500
print(value.nearestBelowThousands) // 17000
print(value.nearestBelow(to: 1000) // 17000
value = 17442
print(value.nearestUpDozens) // 17450
print(value.nearestUpHundreds) // 17500)
print(value.nearestUpThousands) // 18000
print(value.nearestUp(to: 1000) // 18000
按区域设置格式化货币值
print(10.formattedPrice) // "$10.00"
通知中心扩展
从特定队列发布通知
NotificationCenter.default.postNotification("aNotification", queue: DispatchQueue.main)
NotificationCenter.default.postNotification("aNotification", object: aObject queue: DispatchQueue.main)
NotificationCenter.default.postNotification("aNotification", object: aObject userInfo: userInfo queue: DispatchQueue.main)
NSAttributedString扩展
检查是否对所需的子字符串应用了属性
let text = "Hello"
let attrString = NSMutableAttributedString(text: "Hello world")
attrString = attrString.underlined(occurences: text)
attrString.isAttributeActivated(.underlineStyle, appliedOn: text, value: 1) // true
NSLayoutConstraint扩展
watchOS不可用
应用约束乘数(当前仅对宽度和高度有效)
let view = UIView(CGRect(x: 0, y: 0, width: 100, height: 200))
let constraint = NSLayoutConstraint(item: view, attribute: .width, ...)
constraint.apply(multiplier: 0.5, toView: superview)
print(constraint.constants) // 50
let constraint = NSLayoutConstraint(item: view, attribute: .height, ...)
constraint.apply(multiplier0.5, toView: superview)
print(constraint.constants) // 100
NSMutableAttributedString 扩展
着色每次出现的位置
let attrStr: NSMutableAttributedString = NSMutableAttributedString.colored(inText: "hello world", color: .yellow, occurences: "llo")
// OR
let attrStr: NSMutableAttributedString = NSMutableAttributedString(string: "Hello world")
attrStr.color(.yellow, occurences: "llo")
着色每次出现位置之后的全部内容
let attrStr = NSMutableAttributedString.colored(inText: "Hello world", color: .yellow, afterOcurrence: "llo")
// OR
let attrStr = NSMutableAttributedString(string: "Hello world")
attrStr.color(.yellow, afterOcurrence: "llo")
斜体显示每次出现的位置
let attrStr: NSMutableAttributedString = NSMutableAttributedString.struck(inText: "Hello world", occurences: "llo")
// OR
let attrStr = NSMutableAttributedString(string: "Hello world")
attrStr.strike(occurences: "llo")
斜体显示每次出现位置之后的全部内容
let attrStr: NSMutableAttributedString = NSMutableAttributedString.struck(inText: "Hello world", afterOcurrence: "llo")
// OR
let attrStr = NSMutableAttributedString(string: "Hello world")
attrStr.strike(ocurrences: "llo")
下划线显示每次出现的位置
let attrStr: NSMutableAttributedString = NSMutableAttributedString.underlined(inText: "Hello world", occurences: "llo")
// OR
let attrStr = NSMutableAttributedString(string: "Hello world")
attrStr.underline(occurences: "llo")
下划线显示每次出现位置之后的全部内容
let attrStr: NSMutableAttributedString = NSMutableAttributedString.underlined(inText: "Hello world", afterOcurrence: "llo")
// OR
let attrStr = NSMutableAttributedString(string: "Hello world")
attrStr.underline(afterOcurrence: "llo")
为每次出现的文本应用自定义字体
let font = UIFont.boldSystemFont(ofSize: 15)
let attrStr: NSMutableAttributedString = NSMutableAttributedString.font(inText: "hello world", font: font, occurences: "llo")
// OR
let attrStr: NSMutableAttributedString = NSMutableAttributedString(string: "Hello world")
attrStr.font(font, occurences: "llo")
为每次出现位置之后的全部内容应用自定义字体
let font = UIFont.boldSystemFont(ofSize: 15)
let attrStr = NSMutableAttributedString.colored(inText: "Hello world", font: font, afterOcurrence: "llo")
// OR
let attrStr = NSMutableAttributedString(string: "Hello world")
attrStr.font(font, afterOcurrence: "llo")
NSObject 扩展
获取 NSObject
的类名
#if !os(macOS)
let vc = NSViewController()
print(vc.className) // NSViewController
#else
let vc = UIViewController()
print(vc.className) // UIViewController
print(UIViewController.className) // UIViewController
#endif
NSRange 扩展
出现位置之后的范围
let string = "Hello world"
let range = NSRange(text: string, afterOccurence: "llo")
print(range) // location: 3, length: 8
字符串的范围
let string = "Hello world"
let stringToFind = "ello wo"
let range = NSRange(textToFind: stringToFind, in: string)
print(range) // location: 1, length: 7
ReusableFormatters
重复使用格式化器以避免大量分配
SUDateFormatter.shared
SUNumberFormatter.shared
SUByteCountFormatter.shared
SUDateComponentsFormatter.shared
SUDateIntervalFormatter.shared
SUEnergyFormatter.shared
SUMassFormatter.shared
String 扩展
使用索引访问
var string = "hello world"
print(string[0]) // h
print(string[2]) // l
print(string[1...3]) // ell
检查是否包含特定字符串
let string = "Hello world"
print (string.contains(text: "hello")) // true
print (string.contains(text: "hellooooo")) // false
检查是否是数字
var string = "4242"
print(string.isNumber) // true
var string = "test"
print(string.isNumber) // false
检查是否是有效电子邮件地址
var string = "[email protected]"
print(string.isEmail) // true
var string = "test@"
print(string.isEmail) // false
检查是否是有效的IP地址
let ip4 = "1.2.3.4"
let ip6 = "fc00::"
let notIPAtAll = "i'll bribe you to say i'm an ip address!"
ip4.isIP4Address //true
ip4.isIP6Address //false
ip4.isIPAddress //true
ip6.isIP4Address //false
ip6.isIP6Address //true
ip6.isIPAddress //true
notIPAtAll.isIP4Address //false
notIPAtAll.isIP6Address //false
notIPAtAll.isIPAddress //false
将字符串转换为“下划线化”
var camelString = "isCamelled"
print(camelString.uncamelize) // is_camelled
将首字母大写
var string = "hello world"
string = string.capitalizedFirst
print(string)// Hello world
移除前后空格和新行
var string = " I' am a test \n "
print(string.trimmed()) // I'am a test
截断至字符限定长度
var string = "0123456789aaaa"
print(string.truncate(limit: 10)) // 0123456789...
将字符串分割为包含 n 个元素的块
let string = "abcd"
print(string.split(intoChunksOf: 2)) // ["ab", "cd"]
Timer 扩展
每秒钟安排定时器
var count = 0
Timer.every(1.second, fireImmediately: true) { timer in // fireImmediately is an optional parameter, defaults to false
print("Will print every second")
if count == 3 {
timer.invalidate()
}
count++
}
在延迟后安排定时器
Timer.after(2.seconds) { _ in
print("Prints this 2 seconds later in main queue")
}
手动安排定时器
let timer = Timer.new(every: 2.seconds) { _ in
print("Prints this 2 seconds later in main queue")
}
timer.start(onRunLoop: RunLoop.current, modes: RunLoopMode.defaultRunLoopMode)
延迟后手动安排定时器
let timer = Timer.new(after: 2.seconds) { _ in
print("Prints this 2 seconds later in main queue")
}
timer.start(onRunLoop: RunLoop.current, modes: RunLoopMode.defaultRunLoopMode)
URL 扩展
从 URL 获取查询参数
let url = URL(string: "http://example.com/api?v=1.1&q=google")
let queryParameters = url?.queryParameters
print(queryParameters?["v"]) // 1.1
print(queryParameters?["q"]) // google
print(queryParameters?["other"]) // nil
将跳过备份属性添加到您的 URL
let url = URL(string: "/path/to/your/file")
url?.addSkipBackupAttribute() // File at url won't be backupped!
UserDefaults 扩展
使用索引符从 UserDefaults
获取和设置值
let Defaults = UserDefaults.standard
Defaults["userName"] = "test"
print(Defaults["userName"]) // test
检查 UserDefaults
是否具有键
UserDefaults.has(key: "aKey")
// OR
UserDefaults.standard.has(key: "aKey")
从 UserDefaults
中移除所有值
UserDefaults.standard.removeAll()
SwiftUI
UIElementPreview
自动生成包括多个预览
- 默认尺寸预览或专用预览设备
- 启用黑暗模式的预览
- 将项目每个本地化应用于预览
- 应用不同的动态字体大小
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
UIElementPreview(ContentView(),
previewLayout: .sizeThatFits, // default is `.device`
previewDevices: ["iPhone SE"], // default is iPhone SE and iPhone XS Max. Note: it won't be used if `previewLayout` is `.sizeThatFits`
dynamicTypeSizes:[.extraSmall] // default is: .extraSmall, .large, .extraExtraExtraLarge
)
}
}
UIKit 扩展
UIAlertController 扩展
创建自定义的 UIAlertController
let alertController1 = UIAlertController(title: "Title",
message: "Message")
let alertController2 = UIAlertController(title: "Title",
message: "Message",
defaultActionButtonTitle: "Cancel")
let alertController3 = UIAlertController(title: "Title",
message: "Message",
defaultActionButtonTitle: "Cancel",
defaultActionButtonStyle: .cancel)
let alertController1 = UIAlertController(title: "Title",
message: "Message",
defaultActionButtonTitle: "Cancel",
defaultActionButtonStyle: .cancel,
tintColor: .blue)
显示 UIAlertController
alertController.show()
alertController.show(animated: false)
alertController.show(animated: true, completion: {
print("Presented")
})
向 UIAlertController
添加操作
alertController.addAction(title: "ActionTitle")
alertController.addAction(title: "ActionTitle",
style: .destructive)
alertController.addAction(title: "ActionTitle",
style: .destructive,
isEnabled: false)
alertController.addAction(title: "ActionTitle",
style: .destructive,
isEnabled: false,
handler: nil)
UIApplication 扩展
获取当前视图控制器显示
UIApplication.shared.topViewController() // Using UIWindow's rootViewController as baseVC
UIApplication.shared.topViewController(from: baseVC) // topVC from the base view controller
获取应用代理
UIApplication.delegate(AppDelegate.self)
打开应用设置
UIApplication.shared.openAppSettings()
打开应用评价页面
let url = URL(string: "https://itunes.apple.com/app/{APP_ID}?action=write-review")
UIApplication.shared.openAppStoreReviewPage(url)
UIButton 扩展
向按钮添加具有自定义偏移量的右侧图像
let button = UIButton(frame: .zero)
button.addRightImage(image, offset: 16)
UICollectionViewCell 扩展
应用角半径到单元格
let cell = UICollectionViewCell()
cell.applyCornerRadius(10)
当单元格高亮时进行动画
class MyCollectionViewCell: UICollectionViewCell {
// ...
override var isHighlighted: Bool {
willSet {
self.animate(scale: newValue, options: .curveEaseInOut) // Note that the animation is customisable, but all parameters as default value
}
}
// ...
}
UIFont 扩展
获取支持动态字体的字体
let font = UIFont.dynamicStyle(.body, traits: .traitsBold)
UIDevice 扩展
访问您的设备信息
print(UIDevice.idForVendor) // 104C9F7F-7403-4B3E-B6A2-C222C82074FF
print(UIDevice.systemName()) // iPhone OS
print(UIDevice.systemVersion()) // 9.0
print(UIDevice.deviceName) // iPhone Simulator / iPhone 6 Wifi
print(UIDevice.deviceLanguage) // en
print(UIDevice.isPhone) // true or false
print(UIDevice.isPad) // true or false
检查您的系统版本
print(UIDevice.isVersion(8.1)) // false
print(UIDevice.isVersionOrLater(8.1)) // true
print(UIDevice.isVersionOrEarlier(8.1)) // false
强制设备方向
UIDevice.forceRotation(.portrait)
UIDevice.current.forceRotation(.portrait)
UIImage 扩展
从颜色创建图像
let image = UIImage(color: .green)
用颜色填充图像
let image = UIImage(named: "image")
let greenImage = image.filled(with: .green)
将图像与另一图像合并
let image = UIImage(named: "image")
let image2 = UIImage(named: "image2")
let combinedImage = image.combined(with: image2)
更改渲染模式
var image = UIImage(named: "image")
image = image.template // imageWithRenderingMode(.alwaysTemplate)
image = image.original // imageWithRenderingMode(.alwaysOriginal)
UILabel 扩展
将动态文字样式配置到标签上
label.configureDynamicStyle(.body, traits: .traitBold)
检测标签文字是否被截断
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 30, height: 40))
label.text = "I will be truncated :("
print(label.isTruncated()) // true
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 30, height: 40))
label.text = ":)"
print(label.isTruncated()) // false
自定义标签行高
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 30, height: 40))
label.setText("A long multiline text")
label.setLineHeight(0.9)
自定义标签截断文本(替换默认 ...
)
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 30, height: 40))
label.setText("I will be truncated :(", truncatedText: ".")
print(label.text) // I wi.
UIScreen 扩展
获取屏幕方向
if UIInterfaceOrientationIsPortrait(UIScreen.currentOrientation) {
// Portrait
} else {
// Landscape
}
获取屏幕尺寸
print(UIScreen.size) // CGSize(375.0, 667.0) on iPhone6
print(UIScreen.width) // 375.0 on iPhone6
print(UIScreen.height) // 667.0 on iPhone6
print(UIScreen.heightWithoutStatusBar) // 647.0 on iPhone6
获取状态栏高度
print(UIScreen.statusBarHeight) // 20.0 on iPhone6
UIStoryboard 扩展
获取应用的主 Storyboard
let storyboard = UIStoryboard.main
UISwitch 扩展
切换 UISwitch
let aSwitch = UISwitch(frame: CGRect(x: 0, y: 0, width: 100, height: 30))
aSwitch.toggle()
print(aSwitch.isOn) // true
aSwitch.toggle(animated: false)
UITextField 扩展
将动态文字样式配置到文本框上
textField.configureDynamicStyle(.body, traits: .traitBold)
修改清除按钮的图像
let clearButtonImage = UIImage(named: "clear_button")
let textField = UITextField()
textField.setClearButton(with: clearButtonImage)
修改占位符的颜色
let textField = UITextField()
// set `placeholder` or `attributedPlaceholder`
textField.setPlaceHolderTextColor(.blue)
UITextView 扩展
将动态文字样式配置到文本框上
textView.configureDynamicStyle(.body, traits: .traitBold)
UIView 扩展
轻松更改视图的框架
let aView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
aView.x += 100 // move to right
aView.y += 100 // move downwards
aView.width -= 10 // make the view narrower
aView.height -= 10 // make the view shorter
为视图应用圆角半径
let view = UIView()
view.applyCornerRadius(10)
view.applyCornerRadius(20, maskedCorners: [.layerMaxXMaxYCorner])
使用 `accessibilityIdentifier` 查找子视图,适用于测试私有占位符
aView.findView(forIdentifier: "accessibilityIdentifier")
自动本地化你的字符串
aView.translateSubviews()
它会遍历视图的所有子视图,并使用文本/占位符作为密钥在 NSLocalizedString
中。通过在你的 xib / storyboard 中设置你的本地化密钥,只需调用上述方法即可自动翻译所有字符串。
在视图和其父视图之间添加约束
aView.addConstraints() // Add constraints to all edges with zero insets
aView.addConstraints(to: [.top, .bottom]) // Add constraints to top and bottom edges with zero insets
aView.addConstraints(to: [.top, .left], insets: UIEdgeInsets(top: 10, left: 20, bottom: 0, right: 0)) // Add constraints to top and left edges with custom insets
扩展 UIViewController
通过删除以前的视图控制器来重置导航堆栈
let navController = UINavigationController()
navController.pushViewController(vc1, animated: true)
navController.pushViewController(vc2, animated: true)
navController.pushViewController(vc3, animated: true)
vc3.removePreviousControllers(animated: true)
print(navController.viewControllers) // [vc3]
检查 ViewController 是否在屏幕上且未隐藏
let viewController = UIViewController()
print(viewController.isVisible) // false
检查 ViewController 是否模态呈现
let viewController = UIViewController()
print(viewController.isModal)
以模态方式打开 Safari
let url = URL(string: "https://www.apple.com")
vc.openSafariVC(url: url, delegate: self)
将子视图控制器添加到另一个控制器
vc.addChildController(childVC, subview: vc.view, animated: true, duration: 0.35, options: [.curveEaseInOut, .transitionCrossDissolve])
将子视图控制器添加到容器视图中
vc.addChildController(childVC, in: containerView)
移除子视图控制器
vc.removeChildController(childVC)
扩展 AppKit, Cocoa
扩展 NSView
轻松更改视图的框架
let aView = NSView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
aView.x += 100 // move to right
aView.y += 100 // move downwards
aView.width -= 10 // make the view narrower
aView.height -= 10 // make the view shorter
自动本地化你的字符串
aView.convertLocalizables()
它会遍历视图的所有子视图,并使用文本/占位符作为密钥在 NSLocalizedString
中。通过在你的 xib / storyboard 中设置你的本地化密钥,只需调用上述方法即可自动翻译所有字符串。
协议
协议
使用 Storyboards 和 Segues 在 Swift 中执行 ViewController
数据注入的协议。灵感来自 Nastasha 的博客
class RedPillViewController: UIViewController, Injectable {
@IBOutlet weak private var mainLabel: UILabel!
// the type matches the IOU's type
typealias T = String
// this is my original dependency (IOU)
// I can now make this private!
private var mainText: String!
override func viewDidLoad() {
super.viewDidLoad()
// this will crash if the IOU is not set
assertDependencies()
// using the IOU if needed here,
// but using it later is fine as well
mainLabel.text = mainText
}
// Injectable Implementation
func inject(text: T) {
mainText = text
}
func assertDependencies() {
assert(mainText != nil)
}
}
// ViewController that will inject data...
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
switch segueIdentifierForSegue(segue) {
case .TheRedPillExperience
let redPillVC = segue.destinationViewController as? RedPillViewController
redPillVC?.inject("😈")
case .TheBluePillExperience:
let bluePillVC = segue.destinationViewController as? BluePillViewController
bluePillVC?.inject("👼")
}
}
可占用
以下用例适用于 String Array、Dictionary 和 Set
isEmpty
/ isNotEmpty
没有可选类型
var string = "Hello world"
print(string.isNotEmpty) // true
print(string.isEmpty) // false
isNilOrEmpty
仅可选类型
let string: String? = ""
print(string.isNilOrEmpty) // true
Then
Swift初始化器的语法糖
let label = UILabel().then {
$0.textAlignment = .Center
$0.textColor = .blackColor()
$0.text = "Hello, World!"
}
PropertyWrappers
UserDefaultsBacked
对UserDefaults进行类型安全的访问,支持默认值。
struct SettingsViewModel {
@UserDefaultsBacked(key: "search-page-size", defaultValue: 20)
var numberOfSearchResultsPerPage: Int
@UserDefaultsBacked(key: "signature")
var messageSignature: String?
}
其他
UnitTesting
Grand Central Dispatch语法糖
检测UITests是否正在运行
if UnitTesting.isRunning {
// tests are running
} else {
// everything is fine, move along
}
测量测试性能
func testPerformance() {
let measurement = measure {
// run operation
}
}
UI测试
检测UITests是否正在运行
if UITesting.isRunning {
// tests are running
} else {
// everything is fine, move along
}
Shell工具
(仅限macOS)
在系统外壳上运行命令并提供成功、STDOUT和STDERR的返回码。
STDOUT作为连续的String字符串
let (rCode, stdOut, stdErr) = SystemUtility.shell(["ls", "-l", "/"])
// rCode = 0 (which is "true" in shell)
// stdOut = "total 13\ndrwxrwxr-x+ 91 root admin 2912 Feb 11 01:24 Applications" ... etc
// stdErr = [""]
STDOUT作为由换行符分隔的String数组
let (rCode, stdOut, stdErr) = SystemUtility.shellArrayOut(["ls", "-l", "/"])
// rCode = 0 (which is "true" in shell)
// stdOut = ["total 13", "drwxrwxr-x+ 91 root admin 2912 Feb 11 01:24 Applications" ... etc]
// stdErr = [""]
安装
- Xcode 8及其以上版本
- Swift 3.0
- iOS 8.0及其以上版本
- macOS 10.10及其以上版本
- tvOS 9.0及其以上版本
- watchOS 2.0及其以上版本
手动
将SwiftyUtils文件夹复制到您的Xcode项目中。(确保您已经将这些文件添加到您的目标中)
CocoaPods
在Podfile中添加 pod SwiftyUtils
。
Carthage
在Cartfile中添加 github "tbaranes/SwiftyUtils"
。
Swift包管理器
您可以使用Swift包管理器通过在您的Package.swift
文件中添加适当的描述来安装SwiftyUtils
import PackageDescription
let package = Package(
dependencies: [
.Package(url: "https://github.com/tbaranes/SwiftyUtils.git", majorVersion: 0)
]
)
反馈
- 如果您发现了错误,请提交一个问题
- 如果您有功能请求,请提交一个问题
- 如果您想贡献,提交一个pull request
联系
- @tbaranes 在github上
许可协议
SwiftyUtils遵循MIT许可证。有关更多信息,请参阅LICENSE文件。dic.testAll