我会先给你一些背景知识.我正在try 创建一个函数,该函数接受任何符合协议(SomeProtocol)的类型作为参数.因此,我使用名为Currency的静态方法创建了一个 struct ,该 struct 符合SomeProtocol.Type,但是,在try 将该方法作为该泛型函数的参数传递时,我收到了这个错误:"静态成员‘Currency’不能用于协议元类型‘SomeProtocol.Type’".

我只是想重新创建这段SwiftUI代码:

Text(20.0, format: .currency(code: Locale.current.currency?.identifier ?? "USD"))

阅读文档,上面的函数是一个泛型init(),它接受符合某些协议的泛型类型.

init<F>(_ input: F.FormatInput, format: F) where F : FormatStyle, F.FormatInput : Equatable, F.FormatOutput == String

所以,.currency()是一个来自FloatingPointFormatStyle.Currency的静态方法,struct符合FormatStyle.

我的问题是,为什么这在SwiftUI中有效(将符合协议的 struct 中的静态方法作为参数传递给接受符合该协议的任何类型的函数),而不是在我自己的示例中:

protocol SomeProtocol {
    associatedtype SomeType: SomeProtocol
    var a: String { get }
    var b: String { get }
    static func currency(x: Int) -> SomeType
}

func someTest<T>(x: T) -> String where T: SomeProtocol{
    return "this works!"
}

struct AnotherType: SomeProtocol {
    let a = "Test"
    let b = "someTest"

    static func currency(x: Int) -> AnotherType {
        return AnotherType()
    }
}

someTest(x: .currency(x: 20))

推荐答案

请注意,.currency(...)implicit member expression.

隐式成员表达式是在类型推断可以确定隐式类型的上下文中访问类型成员(如枚举用例或类型方法)的一种简化方式.

Swift只知道参数x需要SomeProtocol种类型,但不知道是哪种类型.所以它认为你的意思是:

someTest(x: SomeProtocol.currency(x: 20))

这是无效的.您要呼叫的是哪个实现的currencySomeProtocol中声明的currency方法没有实现!

您只能在协议的特定实现上呼叫currency,例如AnotherType.currency(x: 20).

请注意,内置currency的文档并没有提到"必需的"或"默认提供的实现"之类的内容.SwiftUI所做的是对包含currency实现的协议进行扩展,而不是提出协议要求:

extension SomeProtocol {
    static func currency(x: Int) -> AnotherType {
        return AnotherType()
    }
}

但这仍然不够.你还是不能做到SomeProtocol.currency(...).如果currency使用协议的一些静态要求,该怎么办?Swift 不知道是否有,或者currency是否使用了它们.

因此,您实际上需要:

extension SomeProtocol where Self == AnotherType {
    static func currency(x: Int) -> AnotherType {
        return AnotherType()
    }
}

现在Swift 知道.currency(x: 20)就是AnotherType.currency(x: 20).

请注意,关联的SomeType类型是不必要的.如果需要,您可以添加与此相关的进一步约束,但这种隐式成员表达式不是必需的.

Swift相关问答推荐

自定义完整屏幕封面动画

可编码:将字符串解码为自定义类型(ISO 8601日期,无时间组件)

在列表项内的NavigationLink中的按钮无法正常工作

为什么我的引用类型对象在初始化后有3个强引用?

UITableView未显示类数组数据

体积单位从夸脱转换为杯似乎关闭了

如何在SwiftUI的文本视图中显示NSMutableAttributedString?

物理主体未与 spritekit Swift 的网格图案上的纹理图像对齐

如何使用模型在 SwiftUI 的列表中进行搜索

减小SF符号的边框宽度

为什么我的Swift app不能用xcodebuild构建,但是用XCode可以构建?

如何在类中打印函数

如何从数据中读取以空结尾的字符串?

将数据附加到 Firebase 实时数据库后,NavigationLink 将我重定向到上一个视图

为什么 `map(foo)` 和 `map{ foo($0) }` 返回不同的结果?

找不到目标AAA的 SPM 工件 - 仅限 Xcode 13.3

理解 Swift 2.2 Select 器语法 - #selector()

让我的函数计算数组 Swift 的平均值

快速在 LLDB 中使用 po

SwiftUI:将多个 BindableObjects 放入环境