嵌套协议中的Swift关联类型未得到足够的自动推断 描述

嵌套协议中的Swift关联类型未得到足够的自动推断 描述,swift,xcode,closures,protocols,type-inference,Swift,Xcode,Closures,Protocols,Type Inference,我有一个协议,其中包含一个需要稍后推断的关联类型,名为UIViewRepresentable 然后,添加另一个协议: protocol UIViewRepresentableHelper: UIViewRepresentable { var configuration: (UIViewType) -> () { get set } } extension UIViewRepresentableHelper { func makeUIView(context: UIView

我有一个协议,其中包含一个需要稍后推断的关联类型,名为
UIViewRepresentable

然后,添加另一个协议:

protocol UIViewRepresentableHelper: UIViewRepresentable {
    var configuration: (UIViewType) -> () { get set }
}

extension UIViewRepresentableHelper {
    func makeUIView(context: UIViewRepresentableContext<Self>) -> UIViewType { UIViewType() }
    func updateUIView(_ uiView: UIViewType, context: UIViewRepresentableContext<Self>) { configuration(uiView) }
}
编辑#3 使用单个泛型类:

public protocol UIViewRepresentableHelper: UIViewRepresentable {
    var configuration: (UIViewType) -> () { get set }
}

public extension UIViewRepresentableHelper {
    func makeUIView(context: UIViewRepresentableContext<Self>) -> UIViewType { UIViewType() }
    func updateUIView(_ uiView: UIViewType, context: UIViewRepresentableContext<Self>) { configuration(uiView) }
}

public struct ViewConfigurator<UIViewType: UIView>: UIViewRepresentableHelper {
    public var configuration: (UIViewType) -> ()
    public init(configuration: @escaping (UIViewType) -> ()) {
        self.configuration = configuration
    }
}
或者通过显式地指定泛型参数:

typealias ButtonConfigurator = ViewConfigurator<UIButton>
let buttonConfigurator = ButtonConfigurator { button in
    print(button.title(for: .normal) ?? "empty")
}

var button = UIButton()
buttonConfigurator.configuration(button) // Optional("")
button.setTitle("some title", for: .normal)
buttonConfigurator.configuration(button) // Optional("some title")

编辑#2 因为我声明:

func updateUIView(_ uiView: UITextField, context: Context) {
    
}
但是一旦我把
UIViewType
放进去,错误又回来了,我想我的第一个想法是正确的,编译器不能很好地处理相关的类型和闭包

编辑#1 所以问题实际上是
UIViewType
configuration
没有在同一协议中声明

我可以通过在
UIViewRepresentableHelper

就像这样:

public struct ViewConfigurator<UIViewType: UIView>: UIViewRepresentableHelper

protocol UIViewRepresentableHelper: UIViewRepresentable {
    typealias ViewType = UIViewType
    var configuration: (ViewType) -> () { get set }
}

struct TextFieldView: UIViewRepresentableHelper {
    var configuration: (UITextField)->()
    
}
用法:

let textFieldView = TextFieldView { textField in
    print(textField.text)
}

var textField = UITextField()
textFieldView.configuration(textField) // Optional("")
textField.text = "some text"
textFieldView.configuration(textField) // Optional("some text")


编辑#3 使用单个泛型类:

public protocol UIViewRepresentableHelper: UIViewRepresentable {
    var configuration: (UIViewType) -> () { get set }
}

public extension UIViewRepresentableHelper {
    func makeUIView(context: UIViewRepresentableContext<Self>) -> UIViewType { UIViewType() }
    func updateUIView(_ uiView: UIViewType, context: UIViewRepresentableContext<Self>) { configuration(uiView) }
}

public struct ViewConfigurator<UIViewType: UIView>: UIViewRepresentableHelper {
    public var configuration: (UIViewType) -> ()
    public init(configuration: @escaping (UIViewType) -> ()) {
        self.configuration = configuration
    }
}
或者通过显式地指定泛型参数:

typealias ButtonConfigurator = ViewConfigurator<UIButton>
let buttonConfigurator = ButtonConfigurator { button in
    print(button.title(for: .normal) ?? "empty")
}

var button = UIButton()
buttonConfigurator.configuration(button) // Optional("")
button.setTitle("some title", for: .normal)
buttonConfigurator.configuration(button) // Optional("some title")

编辑#2 因为我声明:

func updateUIView(_ uiView: UITextField, context: Context) {
    
}
但是一旦我把
UIViewType
放进去,错误又回来了,我想我的第一个想法是正确的,编译器不能很好地处理相关的类型和闭包

编辑#1 所以问题实际上是
UIViewType
configuration
没有在同一协议中声明

我可以通过在
UIViewRepresentableHelper

就像这样:

public struct ViewConfigurator<UIViewType: UIView>: UIViewRepresentableHelper

protocol UIViewRepresentableHelper: UIViewRepresentable {
    typealias ViewType = UIViewType
    var configuration: (ViewType) -> () { get set }
}

struct TextFieldView: UIViewRepresentableHelper {
    var configuration: (UITextField)->()
    
}
用法:

let textFieldView = TextFieldView { textField in
    print(textField.text)
}

var textField = UITextField()
textFieldView.configuration(textField) // Optional("")
textField.text = "some text"
textFieldView.configuration(textField) // Optional("some text")




“可以做些什么来摆脱至少一个”什么是“他们”指的是什么?这两条错误消息?(删除的评论;我的复制不正确。)你很清楚;我只是错误地复制了它。@RobNapier最后,你删除的评论很有用;)是的,我想说这对推理机来说只是一座太远的桥。它需要计算出类型以确保它符合,它需要符合以获得扩展,我只是不认为它能计算出来。我没有看到明显的错误;这可能是编译器无法理解的。我用泛型而不是闭包重写了它,它也有同样的问题。我建议在bugs.swfit.org打开一个缺陷。“可以做些什么来摆脱至少一个”他们指的是什么?这两条错误消息?(删除的评论;我的复制不正确。)你很清楚;我只是错误地复制了它。@RobNapier最后,你删除的评论很有用;)是的,我想说这对推理机来说只是一座太远的桥。它需要计算出类型以确保它符合,它需要符合以获得扩展,我只是不认为它能计算出来。我没有看到明显的错误;这可能是编译器无法理解的。我用泛型而不是闭包重写了它,它也有同样的问题。我建议在bugs.swfit.org打开一个缺陷。虽然这允许我从原始位置删除类型,但它迫使我将其添加到其他位置。我正在寻找一种方法,斯威夫特可以自动推断类型为。我告诉它一次,我避免再做一次。(甚至作为一般约束等)。同样,这段代码也会出现同样的问题。我已经用真实世界的信息更新了我的问题。你必须在调用点指定类型。通用解决方案是一种“编码较少”的解决方案。我认为你想做的应该适用于闭包,但事实并非如此。不过,您可以只声明一个采用所需参数类型的方法。我会检查它是否工作时,我有时间,我已经尝试了这个编辑没有运气。不幸的是。是的,我理解为什么由于@RobNapier,我在扩展名中错误地声明了
func updateUIView(uiView:UITextField,context:context)
,虽然这允许我从原始位置删除类型,但它迫使我将其添加到其他位置。我正在寻找一种方法,斯威夫特可以自动推断类型为。我告诉它一次,我避免再做一次。(甚至作为一般约束等)。同样,这段代码也会出现同样的问题。我已经用真实世界的信息更新了我的问题。你必须在调用点指定类型。通用解决方案是一种“编码较少”的解决方案。我认为你想做的应该适用于闭包,但事实并非如此。不过,您可以只声明一个采用所需参数类型的方法。我会检查它是否工作时,我有时间,我已经尝试了这个编辑没有运气。不幸的是,是的,我理解为什么由于@RobNapier,我在扩展名中错误地声明了
func updateUIView(\uiView:UITextField,context:context)