⚡
lighting
Lightning提供了组件,使Swift开发更简单。
如果您想从旧版本迁移,请参阅版本。
组件
📦
属性封装器:@StoredStored
是一个属性封装器,通过内部键值存储来读写值。
与广泛使用的
@UserDefault
属性封装器不同,@Stored
可以内部使用任何符合KeyValueStoreProtocol
的键值存储。在 Lightning 中有两个预定义的键值存储:
默认用户
InMemoryKeyValueStore
:一个使用内部字典存储数据的键值存储。对于单元测试很有用。
定义
final class UserPreferences {
@Stored var temperatureUnit: TemperatureUnit?
@Stored var weightUnit: WeightUnit
// Inject store into wrappers here:
init<S: KeyValueStoreProtocol>(store: S) where S.Key == String {
_temperatureUnit = Stored(key: "temperature-unit", store: store)
_weightUnit = Stored(key: "weight-unit", defaultValue: .grams, store: store)
}
在应用目标中的应用
let store = UserDefaults.standard
let preferences = UserPreferences(store: store)
preferences.temperatureUnit = .celsius
在测试目标中的应用
let store = InMemoryKeyValueStore<String>() // Internally a simple [String: Any] dictionary.
let preferences = UserPreferences(store: store)
preferences.temperatureUnit = .celsius
支持的类型
- 基本类型:
Data
、String
、Date
、NSNumber
、Int
、UInt
、Double
、Float
、Bool
、URL
- 所有
:对任何 类型符合 Storable
。无需额外实现。 - 所有
:对任何 类型符合 StorableCodable
。无需额外实现。 - 任何
Storable
:遵守Storable
协议并为你的类型提供自定义实现。
🗼
通道通道现在是 Rasat 的一部分!
🖊️
StringFormatter// - Perform 05308808080 -> 0 (530) 880 80 80
let phoneFormatter = StringFormatter(pattern: "# (###) ### ## ##")
let formattedNumber = phoneFormatter.format("05308808080") // Returns "0 (530) 880 80 80"
🙈
StringMask// - Perform 1111222233334444 -> ********33334444
let cardMask = StringMask(ranges: [NSRange(location: 0, length: 8)])
let cardMaskStorage = StringMaskStorage(mask: mask)
// 1. Pass it into the storage:
cardMaskStorage.original = "1111222233334444"
// 2. Read masked & unmasked value back:
let cardNo = cardMaskStorage.original // "1111222233334444"
let maskedCardNo = cardMaskStorage.masked // "********33334444"
⚛️
原子原子
是一个线程安全的值容器。
var list = Atomic(["item1"])
// Get value:
let items = list.value
// Set value:
list.value = ["item1", "item2"]
// Read block:
list.read { items in
print(items)
}
// Write block:
list.write { items in
items.append(...)
}
⏱️
定时控制器定时控制器
是对 Timer
的包装,它使得实现倒计时变得简单。
let ticker = Ticker() // or MockTicker()
let timerController = TimerController(total: 60, interval: 1, ticker: ticker)
timerController.startTimer { state in
timerLabel.text = "\(state.remaining) seconds remaining..."
}
🗃️
弱引用与 WeakArray弱引用
是对对象进行弱引用的包装。WeakArray
是一个对元素进行弱引用的Array
。 (类似于NSPointerArray
.)
以下示例展示了如何使用它来实现请求取消。
var liveRequests = WeakArray<URLSessionTask>()
func viewDidLoad() {
super.viewDidLoad()
// Following async requests will be live until we get a response from server.
// Keep a weak reference to each to be able to cancel when necessary.
let offersRequest = viewModel.getOffers { ... }
liveRequests.appendWeak(offersRequest)
let favoritesRequest = viewModel.getFavorites { ... }
liveRequests.appendWeak(favoritesRequest)
}
func viewWillDisappear() {
super.viewWillDisappear()
liveRequests.elements.forEach { $0.cancel() }
liveRequests.removeAll()
}
⌛
ActivityState用于跟踪实时活动的组件。主要用于显示/隐藏加载视图,如下例所示。
var activityState = ActivityState() {
didSet {
guard activityState.isToggled else { return }
if activityState.isActive {
// Show loading view.
} else {
// Hide loading view.
}
}
}
func someProcess() {
activityState.add()
asyncCall1() {
// ...
activityState.add()
asyncCall2() {
// ...
activityState.remove()
}
activityState.remove()
}
}
📱 📲
CollectionChangepublic enum CollectionChange {
case reload
case update(IndexPathSetConvertible)
case insertion(IndexPathSetConvertible)
case deletion(IndexPathSetConvertible)
case move(from: IndexPathConvertible, to: IndexPathConvertible)
}
封装任何集合变化的枚举。可以用于模型UITableView
/UICollectionView
或任何CollectionType
变化。
func addCustomer(_ customer: Customer) -> CollectionChange {
customers.insert(customer, at: 0)
return .insertion(0)
}
Extensions
Lightning提供带有zap
前缀的已知类型的扩展。
String+Helpers
let string = "Welcome"
// Int -> String.Index conversion:
let index1 = string.zap_index(1)
let eChar = string[index1] // "e"
let eChar = string.zap_character(at: 1) // "e"
// NSRange -> Range<String.Index> conversion:
let nsRange = NSRange(location: 0, length: 3)
let substring = string.zap_substring(with: nsRange) // "Wel"
let stringRange = string.zap_range(from: nsRange)
let substring = string.substring(with: stringRange) // "Wel"
// Range validation for NSRange -> Range<String.Index>:
let shortString = "Go"
let intersectedRange = shortString.zap_rangeIntersection(with: nsRange)
// `nsRange` [0, 2] is out of bounds for "Go". Intersection is [0, 1].
Dictionary+Helpers
引入了+
和+=
操作符。
let dict1 = ["k1": "v1", "k2": "v2"]
let dict2 = ["k3": "v3"]
var dict3 = dict1 + dict2 // [(k1: v1), (k2: v2), (k3: v3)]
dict3 += ["k4": "v4"] // [(k1: v1), (k2: v2), (k3: v3), (k4: v4)]
dict3 += ["k4": "xx"] // [(k1: v1), (k2: v2), (k3: v3), (k4: xx)]
Bundle+Helpers
提供版本字符串辅助工具。
// Version field:
bundle.zap_shortVersionString // 1.2.1
// Build field:
bundle.zap_versionString // 345
安装
使用 CocoaPods
将以下行添加到您的 Podfile
文件中
pod 'Lightning'
Carthage
使用将以下行添加到您的 Cartfile
文件中
github "gokselkoksal/Lightning"
手动方式
将 Sources
文件夹拖放到您的项目内。
强烈推荐使用类似 CocoaPods
或 Carthage
的依赖管理器。
许可证
Lightning 在 MIT 许可证 下可用。