烹饪 (Cooking)

Cook classes/structs with the taste you love.
Naming your extensions in the Swifty way people love.

Swift 的 extension (扩展) 非常强大。我们不仅可以扩展自己的 class (类) / struct (结构体),还可以扩展任何框架的 class (类) / struct (结构体)。

嗯,函数命名冲突在 extension (扩展) 中是一个常见问题。过去人们使用 xxx_ 前缀来解决这个问题。现在人们使用一种更智能、更简洁,最终更符合 Swift 风格的方法。

框架 过去 现在
RxSwift label.rx_text label.rx.text
SnapKit view.snp_makeConstraints view.snp.makeConstraints

Cooking (烹饪) 是一个帮助你采用这种 Swift 风格来命名 extension (扩展) 的库。

用法

无论是 class (类) 还是 struct (结构体),都必须遵循 Edible (可食用) 协议才能拥有带有 .cook 的包装器。

然后使用 where 约束来扩展 Cooking,从而扩展你的 class (类) 或 struct (结构体)。 你将必须使用 ingredient (原料) 来引用实例,而不是使用 self

对于 class (类),约束可以使用 ==:
对于 struct (结构体),约束必须使用 ==

import Cooking

extension String: Edible {}
//  Use `==` for structs.
extension Cooking where Ingredient == String {

	static func bitterOne() -> String {
		return "😭😭😭"
	}

	func sweeten() -> String {
		return ingredient.replacingOccurrences(of: "😭", with: "😋")
	}
}

let bitterString = String.cook.bitterOne()
//  bitterString = "😭😭😭"
let sweetString  = bitterString.cook.sweeten()
//  sweetString  = "😋😋😋"

extension UIView: Edible {}
extension Cooking where Ingredient: UIView {
	func area() -> CGFloat {
		return ingredient.frame.width * ingredient.frame.height
	}
}

let view = UIView(frame: .init(origin: .zero, size: .init(width: 50, height: 20)))
let area = view.cook.area()
//  area = 1000

安装

CocoaPods

CocoaPods 是 Cocoa 项目的依赖管理工具。 你可以使用以下命令安装它

$ gem install cocoapods

要在你的 Xcode 项目中使用 CocoaPods 来使用 Cooking (烹饪),请在你的 Podfile 中指定它

pod 'Cooking'

然后,运行以下命令

$ pod install

Swift Package Manager

将此项目作为依赖项添加到你的 Package.swift 文件中。

.Package(url: "https://github.com/ShaneQi/Cooking.git", majorVersion: 1, minor: 0)

手动

在你的项目中包含文件 Sources/Cooking.swift

局限性

  1. 无法扩展带有 mutating func (可变函数) 的结构体。
extension String: Edible {}

extension Cooking where Ingredient == String {

	mutating func addExclamation() {
		ingredient.append("!")
	}

}

"hello".cook.addExclamation()
// ERROR: ^ Cannot use mutating member, `cook` is a get-only property.
  1. 无法扩展泛型类型。
extension Optional: Edible {}  
                               
extension Cooking where Ingredient == Optional {
//                                ERROR: ^ Reference to generic type 'Optional' requires arguments in <...>                          

	func someFunction() {}

}

许可

Apache-2.0