This page looks best with JavaScript enabled

SwiftUI Picker Implementation

 ·  ☕ 1 min read

实现封装 SwiftUI Picker 控件,达到通过构造不同类型的数据,就能渲染对应类型的 Picker。(The SwiftUI Picker control is encapsulated, so that by constructing different types of data, the corresponding type of Picker can be rendered.)

Step1 Picker data structrure

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class IdentifiableString: Identifiable {
    
    internal init(s: String) {
        self.str = s
        self.id = s
    }
    
    let str: String
    var id: String
}

open class MPickerData<Content> {
    
    public init(title: String, key: String, values: [Content]) {
        self.title = title
        self.key = key
        self.values = values
        self.select = KV.shared.get(key: key)
    }
    
    let title: String
    let key: String
    let values: [Content]
    var select: Content?
    
    var idValues: [IdentifiableString] {
        values.map { item in
            IdentifiableString(s: "\(item)")
        }
    }
    
    open func binding() -> Binding<String>? {
        return nil
    }
    
    func updateSelect(_ newValue: Content) {
        self.select = newValue
        KV.shared.set(key: self.key, value: newValue)
    }
}
  • KV: UserDefaults wraper class

Step2 Implement for some types

Int Picker

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public class MIntPicker: MPickerData<Int> {
    
    public override func binding() -> Binding<String> {
        let binding = Binding<String> {
            return "\(self.select ?? KV.shared.get(key: self.key) ?? 0)"
        } set: { newValue in
            if let nInt = Int(newValue) {
                self.updateSelect(nInt)
            }
        }
        return binding
    }
}

String Picker

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
public class MStringPicker: MPickerData<String> {
    
    public override func binding() -> Binding<String> {
        let binding = Binding<String> {
            return self.select ?? KV.shared.get(key: self.key) ?? ""
        } set: { newValue in
            self.updateSelect(newValue)
        }
        return binding
    }
}

Step3 Implement Picker View

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import SwiftUI

struct MPickerView<Content>: View {
    
    @State var pickerData: MPickerData<Content>
    
    var body: some View {
        VStack {
            Text(pickerData.title).font(.title)
            if let binding = pickerData.binding() {
                Picker(pickerData.title, selection: binding) {
                    ForEach(pickerData.idValues) { idV in
                        Text(idV.str)
                    }
                }.pickerStyle(WheelPickerStyle())
            }
        }
    }
}

Usage

1
2
3
4
5
6
7
8
let pickers = [
	MIntPicker(title: "Select Int", key: "key_int", values: [1, 2, 3, 4]),
	MFloatPicker(title: "Select Float", key: "key_float", values: [1.0, 2.4, 3.5, 4.6]),
	MDoublePicker(title: "Select Double", key: "key_double", values: [1.1, 2.2, 3.3333, 4.56]),
	MStringPicker(title: "Select String", key: "key_string", values: ["aaa", "bbb", "ccc", "ddd"])
]

let pickerView = MPickerView(pickerData: pickers)
Support the author with
alipay QR Code
wechat QR Code

Yang
WRITTEN BY
Yang
Developer