【问题标题】:Value of protocol type '*' cannot conform to '*'; only struct/enum/class types can conform to protocols协议类型'*'的值不能符合'*';只有结构/枚举/类类型可以符合协议
【发布时间】:2021-02-15 16:02:59
【问题描述】:

我在尝试这个时遇到了上述错误:

    protocol Style {}
    
    struct StyleA: Style {}
    struct StyleA: Style {}
    struct StyleA: Style {}

    struct Preset: Identifiable {
        let id: UUID = UUID()
        let title: String
        let style: Style
    }

    extension View {
        public func applyStyle<S>(_ style: S) where S : Style {
            // USe the style here
        }
    }
    

    // Initializg the data
    static let mockedData: [Preset] = [
        .init(title: "Title A", style: StyleA()),
        .init(title: "Title A", style: StyleB()),
        .init(title: "Title A", style: StyleC()),
    ]
    
// This line gives the error
    myView.applyStyle(mockedData.first!.style)


我该如何解决?它不应该解决具体类型吗?

感谢您的帮助。

【问题讨论】:

  • 那是因为在 swift 协议中不会对自己进行确认。阅读:stackoverflow.com/questions/33112559/…
  • 一个问题是你必须公开“协议样式”(因为你的函数是公开的
  • 我猜,如果您在视图主体内使用 applyStyle ...那么此函数不会返回视图,所以这也是一个函数...请添加可重现的代码。

标签: swift swiftui swift-protocols


【解决方案1】:

您遇到了protocols not conforming to themselves 的问题。通过将applyStyle 设为非泛型可以轻松解决您的问题,因为Style 可以用作具体类型。

extension View {
    public func applyStyle(_ style: Style) {
        // USe the style here
    }
}

【讨论】:

  • 我只想从方法名func apply(_ style: Style)中删除Style
  • @LeoDabus 在这种情况下,我认为func apply(style: Style) 会更自然地阅读,但这与OP的问题并不真正相关。
  • 当然与问题无关。无论如何我认为当有单个参数style 是不需要的,一般不使用
【解决方案2】:

由于 Preset 成员样式是 Style,而不是任何具体类型,所以不需要 applyStyle 是通用的,你可以简单地说:

  public func applyStyle(_ style: Style) 

【讨论】:

    【解决方案3】:

    试试

    public protocol Style {}
    
    struct StyleA: Style {}
    struct StyleB: Style {}
    struct StyleC: Style {}
    
    struct Preset: Identifiable {
        let id: UUID = UUID()
        let title: String
        let style: Style
    }
    
    extension View {
        public func applyStyle(_ style: Style){
            // USe the style here
        }
    }
    
    
    // Initializg the data
    let mockedData: [Preset] = [
        .init(title: "Title A", style: StyleA()),
        .init(title: "Title A", style: StyleB()),
        .init(title: "Title A", style: StyleC()),
    ]
    
    myView.applyStyle(mockedData.first!.style)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-12
      相关资源
      最近更新 更多