Burritos 0.0.3

Burritos 0.0.3

Guillermo Muntaner 维护。



Burritos 0.0.3

🌯🌯Burritos

Bitrise Build Status Swift Package Manager Platform

一组经过良好测试的 Swift 属性包装器。

要求

Xcode 11 & Swift 5

安装

Swift 包管理器

Xcode 11+ 集成

  1. 打开 MenuBarFileSwift Packages添加包依赖...
  2. 粘贴仓库 URL https://github.com/guillermomuntaner/Burritos 并点击下一步。
  3. 选择您的规则。由于此包处于预发布开发阶段,建议您指定一个具体的标签以避免拉取破坏性变更。

Package.swift

如果您已经有了 Package.swift 或您正在构建自己的包,请添加一个新的依赖项。

dependencies: [
    .package(url: "https://github.com/guillermomuntaner/Burritos", from: "0.0.3")
]

Cocoapods

将 Burritos 添加到您的 Podfile 中。

pod 'Burritos', '~> 0.0.3'

每个包装器都是一个子模块,因此您只需添加所需的那些。

pod 'Burritos/Copying', '~> 0.0.3'
pod 'Burritos/UndoRedo', '~> 0.0.3'
pod 'Burritos/UserDefault', '~> 0.0.3'

@AtomicWrite

一种属性包装器,可以为包装的属性提供原子的写入访问。读取访问不是原子的,但与写入和修改操作是互斥的。可以通过包装器的 mutate 方法执行原子修改(读取-修改-写入)。

@Atomic var count = 0

// You can atomically write (non-derived) values directly:
count = 99

// To mutate (read-modify-write) always use the wrapper method:
DispatchQueue.concurrentPerform(iterations: 1000) { index in
    _count.mutate { $0 += 1 }
}

print(count) // 1099

@Clamping

一种属性包装器,它会自动将其包装值钳位到指定的范围内。

@Clamping(range: 0...1)
var alpha: Double = 0.0

alpha = 2.5
print(alpha) // 1.0

alpha = -1.0
print(alpha) // 0.0

@Copying

一种属性包装器,它围绕 NSCopying 来进行复制,不仅在初始化时复制值,在重新分配时也复制。如果您厌倦了调用 .copy() as! X,那么您一定会喜欢这个。

@Copying var path: UIBezierPath = .someInitialValue

public func updatePath(_ path: UIBezierPath) {
    self.path = path
    // You don't need to worry whoever called this method mutates the passed by reference path.
    // Your stored self.path contains a copy.
}

@DefaultValue

一种属性包装器,它围绕一个隐式非可选值,它降级到给定的默认值。

@DefaultValue(default: 0)
var count
count = 100
// or
@DefaultValue(default: 0)
var count = 100

// Assigning nil resets to the default value
print(count) // 100
count = nil
print(count) // 0

@DynamicUIColor

这是一个围绕UIColor的属性包装器,支持深色模式。

默认情况下,在iOS >= 13中,它使用新的系统级界面样式特性和动态UIColor构造函数来支持深色模式,无需额外努力。在之前的iOS版本中,它默认为浅色。

@DynamicUIColor(light: .white, dark: .black)
var backgroundColor: UIColor

// The color will automatically update when traits change
view.backgroundColor = backgroundColor

为了支持旧版iOS版本和自定义逻辑(例如,应用设置中的开关),构造函数可以接受一个额外的style闭包,该闭包动态指定要使用哪种颜色。返回一个nil值将导致先前的默认行为。通过这样做可以更容易地实现向后兼容性:

let color = DynamicUIColor(light: .white, dark: .black) {
    if #available(iOS 13.0, *) { return nil }
    else { return Settings.isDarkMode ? .dark : .light }
}

view.backgroundColor = color.value

// On iOS <13 you might need to manually observe your custom dark
// mode settings & re-bind your colors on changes:
if #available(iOS 13.0, *) {} else {
    Settings.onDarkModeChange { [weak self] in
        self?.view.backgroundColor = self?.color.value
    }
}

原始想法来源于@bardonadam

@EnvironmentVariable

一个用于设置和获取系统环境变量值的属性包装器。

@EnvironmentVariable(name: "PATH")
var path: String?

// You can set the environment variable directly:
path = "~/opt/bin:" + path!

@Expirable

围绕可以过期的值的一个属性包装器。在给定持续时间或过期日期之后获取值将返回nil。

@Expirable(duration: 60)
var apiToken: String?

// New values will be valid for 60s
apiToken = "123456abcd"
print(apiToken) // "123456abcd"
sleep(61)
print(apiToken) // nil

// You can also construct an expirable with an initial value and expiration date:
@Expirable(wrappedValue: "zyx987", expirationDate: date, duration: 60)
var apiToken: String?
// or just update an existing one:
_apiToken.set("zyx987", expirationDate: date)

由@v_pradeilles提供。

@LateInit

使用属性包装器重新实现了Swift的隐式可选。

var text: String!
// or 
@LateInit var text: String

// Note: Accessing it before initializing will result in a fatal error:
// print(text) // -> fatalError("Trying to access LateInit.value before setting it.")

// Later in your code:
text = "Hello, World!"

@Lazy

一个属性包装器,它将实例化推迟到第一次读写访问。它是一个使用属性包装器重新实现的Swift lazy修饰符。

@Lazy var result = expensiveOperation()
...
print(result) // expensiveOperation() is executed at this point

lazy之上,它还提供将包装器重置为其“未初始化”状态的功能。

@LazyConstant

等同于@Lazy,并防止包装值的更改或修改。

@LazyConstant var result = expensiveOperation()
...
print(result) // expensiveOperation() is executed at this point

result = newResult // Compiler error

注意:该包装器防止重新分配包装属性的值,但不能重新分配包装器本身。重新分配包装器(例如:_value = LazyConstant(wrappedValue: "Hola!"))是可能的,由于包装器本身需要声明为变量,无法防止。

@Trimmed

一个包装器,在初始化和重新分配时自动修剪字符串。

@Trimmed
var text = " \n Hello, World! \n\n    "

print(text) // "Hello, World!"

// By default trims white spaces and new lines, but it also supports any character set
@Trimmed(characterSet: .whitespaces)
var text = " \n Hello, World! \n\n    "
print(text) // "\n Hello, World! \n\n"

@UndoRedo

一个包装器,自动存储历史,并支持撤销和重做操作。

@UndoRedo var text = ""

text = "Hello"
text = "Hello, World!"

_text.canUndo // true
_text.undo() // text == "Hello"

_text.canRedo // true
_text.redo() // text == "Hello, World!"

您可以使用canUndocanRedo属性随时检查是否可以撤销或重做,这两个属性可能特别有助于启用/禁用用户界面按钮。

原始想法来自@JeffHurray

@UserDefault

提供了对UserDefaults的安全访问,并支持默认值。

@UserDefault("test", defaultValue: "Hello, World!")
var test: String

默认情况下,它使用标准用户默认值。您可以通过其构造函数传递任何其他您希望使用的UserDefaults实例,例如在您使用应用程序组时。

let userDefaults = UserDefaults(suiteName: "your.app.group")
@UserDefault("test", defaultValue: "Hello, World!", userDefaults: userDefaults)
var test: String

@Cached

待办事项

@Dependency (服务定位器模式)

待办事项

线程安全

待办事项

命令行参数

待办事项

属性观察器 -> willSet, didSet !

待实现

打印/日志

待实现:打印/记录设置的任何值。

关于属性包装器

引用 属性包装器提议 描述

属性包装器是一种机制,用于抽象反复出现的属性实现模式。

👉你知道吗:属性包装器是在2019年WWDC期间由苹果公司宣布的。它们是 SwiftUI 语法糖中的基本组件,因此苹果公司在Swift 5.1的第一个beta版本中推入了它们,跳过了正常的Swift Evolution过程。这个过程在WWDC之后继续进行,经历了3次审查,最终在Xcode 11 beta 4中定稿。

有趣的阅读材料

其他语言中的等效项

许可证

Burritos 采用了 MIT 许可协议