🐞has non-Sendable type
⟩
Swift ⟩ Concurrency ⟩ Sendable ⟩ 🐞 has non-Sendable type
Stored property 'shape' of 'Sendable'-conforming struct 'MyAnyShape' has non-sendable type '(CGRect)->Path'
import SwiftUI
// ⭐️ Shape is Sendable
struct MyAnyShape: Shape {
// ⭐️ properties must be Sendable too.
private let shape: (CGRect) -> Path // 🐞 error
init<S: Shape>(_ wrapped: S) {
self.shape = { rect in
wrapped.path(in: rect)
}
}
func path(in rect: CGRect) -> Path {
shape(rect)
}
}錯誤原因
MyAnyShape遵循 Shape,但 Shape 隱含遵循 Sendable 的規定(用於 Concurrency 的安全保障)。Sendable要求struct中所有屬性也必須是Sendable。但
shape屬性是閉包(closure),並不自動符合 Sendable,因為它可能捕獲非 Sendable 的值。
Swift Concurrency 的影響
在 Swift 5.5 或更高版本中,並行程式設計(Concurrency)會對某些類型進行更嚴格的型別檢查,特別是用於 @Sendable 閉包的情況。
解決方案
方案一:直接儲存 Shape 實例(wrappedShape),而不是閉包(closure),完全避開 Sendable 的問題。這樣的寫法具有較大的靈活性,如果你有很多種類的 Shape,建議用此寫法。
import SwiftUI
struct MyAnyShape: Shape {
// ⭐️ 直接儲存 Shape 實例
private var wrappedShape: any Shape
init<S: Shape>(_ wrapped: S) {
self.wrappedShape = wrapped
}
func path(in rect: CGRect) -> Path {
wrappedShape.path(in: rect)
}
}方案二:如果 Shape 類型有限,可用 enum 來區分不同的形狀:
import SwiftUI
// ⭐️ 直接用 enum 管理形狀,不需用泛型或閉包
enum MyShape: Shape {
case circle
case roundedRectangle(cornerSize: CGSize)
// ⭐️ Shape requirement
func path(in rect: CGRect) -> Path {
switch self {
case .circle:
return Circle().path(in: rect)
case .roundedRectangle(let cornerSize):
return RoundedRectangle(cornerSize: cornerSize).path(in: rect)
}
}
}👉 應用: view.clipShape()
方案三:將 MyAnyShape 明確標記為不需符合 Sendable。適合熟悉 Swift Concurrency,且確認程式邏輯是 thread-safe 時使用。
import SwiftUI
struct MyAnyShape: Shape {
// ⭐️ 不符合 Sendable 的屬性
private let shape: (CGRect) -> Path
init<S: Shape>(_ wrapped: S) {
self.shape = { rect in
wrapped.path(in: rect)
}
}
func path(in rect: CGRect) -> Path {
shape(rect)
}
}
// ⭐️ 添加 @unchecked Sendable 以避免 Sendable 錯誤
extension MyAnyShape: @unchecked Sendable {}🅿️ Shape: must be Sendable.
📦 AnyShape:type-erased shape value.
Last updated
Was this helpful?