簡體   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