繁体   English   中英

如何使结构符合自定义协议?

[英]How to make struct to conform a custom protocol?

我在 swift UI 中使用了预构建下拉菜单之一,它使用以下结构来列出选项,

struct DropdownOption: Hashable {
    let key: String
    let value: String
    public static func == (lhs: DropdownOption, rhs: DropdownOption) -> Bool {
        return lhs.key == rhs.key
    }
}

我有下拉 UI 显示列表

struct DropdownSelector: View {
    @State var topSelection: ThreeStateBox = .partial
    @State private var shouldShowDropdown = false
    @State private var selectedOption: DropdownOption? = nil

    var placeholder: String
    var options: [DropdownOption]
    var onOptionSelected: ((_ option: DropdownOption) -> Void)?
    var onDropdownSelected: (() -> Void)
    private let buttonHeight: CGFloat = 30

    var body: some View {
        VStack{
            Button(action: {
                self.shouldShowDropdown.toggle()
                onDropdownSelected()
            }) {
                HStack {
                    
                    ThreeStateBoxView(state: $topSelection).frame(width: 20, height: 20, alignment: .leading).padding(.leading, 1)
                    
                    Text(selectedOption == nil ? placeholder : selectedOption!.value)
                        .font(.system(size: 12))
                        .foregroundColor(selectedOption == nil ? Color.black: Color.black)
                    
                    Spacer()
                    Image(self.shouldShowDropdown ? "Dropdown" : "DropDownUp")
                    
                        .frame(width: 9, height: 5)
                        .font(Font.system(size: 9, weight: .medium))
                        .foregroundColor(Color.black)
                    Spacer()
                }.padding([.leading])
            }
            .frame(width: nil, height: self.buttonHeight, alignment: .leading)
            .cornerRadius(5)
            .overlay(
                RoundedRectangle(cornerRadius: 0)
                    .stroke(Color.clear, lineWidth: 1)
            )
            .overlay(
                VStack {
                    Image("top-image")
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .scaledToFit()
                    if self.shouldShowDropdown {
                        Spacer(minLength: buttonHeight + 1)
                        Dropdown(options: self.options, onOptionSelected: { option in
                            shouldShowDropdown = false
                          //  selectedOption = option
                            self.onOptionSelected?(option)
                        })
                    }
                }, alignment: .topLeading
            )
            .background(
                RoundedRectangle(cornerRadius: 5).fill(Color.lightGray)
            )
            
        }
    }
}

现在我希望选项列表依赖于协议而不是具体类型

protocol MyProtocol : Hashable {
    associatedtype  key
    associatedtype  value

}
extension MyProtocol  {
    typealias key = String
    typealias value = String
    static func ==(lhs: Self, rhs: Self) -> Bool {
        return Self.key == Self.key
    }

}

struct DropdownRow: View {
    var option: MyProtocol
    var onOptionSelected: ((_ option: DropdownOption) -> Void)?
    @State var isChecked : Bool = false
    var body: some View {
        Button(action: {
            if let onOptionSelected = self.onOptionSelected {
                onOptionSelected(self.option)
            }
        }) {
            HStack {
                CheckBoxView(checked: $isChecked,tickColor : .black,unTickColor: .gray, borderColorTick: .clear,borderColorUnTick: .gray )
                Text(self.option.value)
                    .font(.system(size: 12))
                    .foregroundColor(Color.black)
                Spacer()
            }.background(Color.lightGray)
        }
        .padding(.horizontal, 17)
        .padding(.vertical, 2)
        .background(Color.lightGray)
    }
}

我收到错误,因为 Protocol 'MyProtocol' 只能用作通用约束,因为它具有 Self 或关联的类型要求? 解决这个问题的任何技巧

这是可能的方法(使用 Xcode 13.4 / iOS 15.5 测试)

protocol MyProtocol: Hashable {    // declaration of interface
    associatedtype Key: Equatable
    associatedtype Value

    var key: Key { get }
    var value: Value { get }
}

extension MyProtocol  {
    static func ==(lhs: Self, rhs: Self) -> Bool {
        lhs.key == rhs.key
    }
}

struct DropdownRow<Option: MyProtocol>: View {   // << generics dependency
    var option: Option   // << here !!

    var body: some View {
        // ... other code here
    }
}

struct DropdownOption: MyProtocol {  // concrete type
    let key: String
    let value: String
}

func demo() -> some View {
    DropdownRow(option: DropdownOption(key: "", value: ""))
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM