闪电 5.0.0

闪电 5.0.0

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

Goksel Koksal维护。



闪电 5.0.0

lighting

Carthage CocoaPods CI Status Platform Language License

Lightning提供了组件,使Swift开发更简单。

如果您想从旧版本迁移,请参阅版本

组件

属性封装器:@Stored📦

Stored 是一个属性封装器,通过内部键值存储来读写值。

与广泛使用的@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

支持的类型

  • 基本类型DataStringDateNSNumberIntUIntDoubleFloatBoolURL
  • 所有:对任何类型符合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()
  }
}

CollectionChange📱📲

public 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 文件夹拖放到您的项目内。

强烈推荐使用类似 CocoaPodsCarthage 的依赖管理器。

许可证

Lightning 在 MIT 许可证 下可用。