前置文档/参考资料
download.swift.org/docs/assets…
前言
咱们一般期望对项目里的资源文件(如颜色/图片/字体)有一些函数能提供静态拜访支撑,以此获得 IDE 的上下文自动补全支撑。
最简略的方式是在 UIColor/UIImage/UIFont 等资源类型上直接运用 extension 进行扩展完成,可是这种办法往往会带来命名抵触,导致事务方一起 import 两个基础组件时被逼运用full qualified name来解决,或者有时无法解决,成为编译时错误。
// Module A
extension UIImage { public static var like: UIImage { ... } }
struct Foo {}
// Module B
extension UIImage { public static var like: UIImage { ... } }
struct Foo {}
// Business Module C
import A
import B
UIImage.like // ❌
let a = A.Foo()
let b = B.Foo()
-
ObjectiveC 的思路是经过在命名上参加 namespace 来削减抵触的或许
-
Swift不鼓舞在命名上参加namespace,因此咱们能够经过 namespace 占位Wrapper类型来完成
下面介绍在 西瓜视频 Swift 中常见的几种 namespace 处理办法实践
实践
非 Protocol 类型
✅ 根据协议完成的Wrapper
假如需要在非Protocol类型上添加namespace是能够经过协议承继完成的
public struct XIGWrapper<Base> {
public let base: Base
public init(_ base: Base) {
self.base = base
}
}
public protocol XIGProtocol {}
public extension XIGProtocol {
var xig: XIGWrapper<Self> {
return XIGWrapper(self)
}
static var xig: XIGWrapper<Self>.Type {
return XIGWrapper.self
}
}
然后比方期望运用 Color.xig.red 和 xxColor.xig.opacity(xx) 就能够写出如下代码
extension Color: XIGProtocol {}
extension XIGWrapper where Base == Color {
public func opacity(_ value: Double): Color { ... }
public static var red: Color { ... }
}
// Usage
Color.xig.red
xxColor.xig.opacity(xx)
Protocol 类型
UIKit 框架选用 ObjectiveC + OOP 规划,大部分类型为 NSObject + class
SwiftUI 框架选用 Swift + POP 规划,大部分类型为 struct + protocol
❌ 根据协议完成的Wrapper
可是假如是带 Protocol 类型,如 View 和 ButtonStyle,工作就会有些不太一样
首先咱们无法经过上面的extension办法来完成
extension View: XIGProtocol {} // ❌ Extension of protocol 'View' cannot have an inheritance clause
✅ 根据结构扩展的Wrapper
咱们能够选用另一种方式来进行Wrapper
public struct XIG<Content> {
let content: Content
public init(_ content: Content) {
self.content = content
}
}
Instance 办法/属性
然后比方期望运用 Text(“xx”).xig.shadowStyle1 就能够写出如下代码
extension View {
public var xig: XIG<Self> { XIG(self) }
public static var xig: XIG<Self>.Type { XIG<Self>.self }
}
extension XIG where Content: View {
public func shddowStyle1() -> some View{
content.shadow(xx)
}
}
// Usage
Text("xx").xig.shadowStyle1
Static 办法/属性
可是关于 static 办法推导现在没有找到适宜的办法
传统上不必命名空间咱们是这样编写
extension ButtonStyle where Self == BorderedButtonStyle {
static var hello: some ButtonStyle { HelloButtonStyle() }
}
struct HelloButtonStyle: ButtonStyle { xx }
// Usage
Text("xx").buttonStyle(.hello)
可是这里咱们仍然会报错
extension XIG where Content == BorderedButtonStyle {
static func hello: some ButtonStyle { HelloButtonStyle() }
}
struct HelloButtonStyle: ButtonStyle { xx }
// Usage
Text("xx").buttonStyle(.xig.hello) // ❌ Contextual member reference to static property 'xig' requires 'Self' constraint in the protocol extension
Text("xx").buttonStyle(BorderedButtonStyle.xig.hello)
extension XIG where Content: ButtonStyle {
static func hello: some ButtonStyle { HelloButtonStyle() }
}
struct HelloButtonStyle: ButtonStyle { xx }
// Usage
Text("xx").buttonStyle(.xig.hello) // ❌ Contextual member reference to static property 'xig' requires 'Self' constraint in the protocol extension
Text("xx").buttonStyle(BorderedButtonStyle.xig.hello)
一种临时解决方案
public struct XIGStatic<Content> {
public init(_ content: Content.Type) {}
}
extension SwiftUI.ButtonStyle {
public static var xig: XIGStatic<Self> { XIGStatic(Self.self) }
}
// Usage
public struct AnyButtonStyle: ButtonStyle {
public func makeBody(configuration: Configuration) -> some View { ... } // Unimplement
}
extension ButtonStyle where Self == AnyButtonStyle {
public static var xig: XIGStatic<AnyButtonStyle> { XIGStatic(AnyButtonStyle.self) }
}
struct HelloButtonStyle: ButtonStyle { ... }
extension XIGStatic where Content == AnyButtonStyle {
var hello: some ButtonStyle { HelloButtonStyle() }
}
// Then we could final use the following code in business code
Text("Hello").buttonStyle(.xig.hello) //
论坛讨论贴:
forums.swift.org/t/namespace…