[英]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.