Closed shippingpark closed 2 weeks ago
@MainActor @preconcurrency struct Picker<Label, SelectionValue, Content> where Label : View, SelectionValue : Hashable, Content : View
label
selectionValue
content
Hashable์ด๋?
์ฐ๋ฆฌ๊ฐ ์๋ dictionary ๋ key-value๋ก ๊ฐ์ ์ ์ฅํ๋๋ฐ, ์ด๋ฌํ ๋์ ๋๋ฆฌ๊ฐ hash table ์ด๋ผ๋ ๊ฒ์ผ๋ก ๊ตฌํ๋์ด ์๋ค๊ณ ํจ
dictionary
hash table
ํด์ ํ ์ด๋ธ์ ๋ฐฐ์ด๋ก ๊ตฌํ์ด ๋์ด ์๋๋ฐ,
์ด๋ฐ ์์ผ๋ก key ๊ฐ์ ํด์ฑ ํจ์์ ๋ฃ์ด ํด์ํ์ฌ โ ๋ฐฐ์ด์ ์ฃผ์ ๊ฐ์ ์ป๊ณ , ๊ทธ ์ฃผ์๊ฐ์ ๋ง๋ index์ value ๊ฐ์ ์ ์ฅํ๋ค๊ณ ํจ. ์ด๋, ํด์ํ ์ด๋ธ์ ์์๋ฅผ ์งํค์ง ์๊ณ ์ ์ฅ ๋จ!!
๋ฐ๋ผ์ ๋ฐฐ์ด์ ์ ์ฅ๋ ๊ฐ์ ์๊ณ ์ถ๋ค๋ฉด, index ๊ฐ์ ์์์ผ ํ๋๋ฐ ์ด index ๊ฐ์ด ์์๋๋ก ๋์ด ์์ง ์๊ธฐ ๋๋ฌธ์ key ๊ฐ์ ์์์ผ ํ๋ ๊ฒ์ (์ฐ๋ฆฐ value๊ฐ ์ ์ฅ๋ ํด์ํ ์ด๋ธ์ index๋ฅผ ๋ชจ๋ฆ
โ ์ฆ Key๋ฅผ ํตํด ํด์ํ ์ด๋ธ์ index๋ฅผ ์์์ผ ํด๋น value์ ์ ๊ทผํ ์ ์๊ฒ ๋จ
๋ฐ๋ผ์ ํด์ํ ์ด๋ธ์ด๋ key ๋ผ๋ ๊ฒ์ ํด์ ํจ์๋ฅผ ์ด์ฉํด ์ฃผ์๊ฐ(index)๋ก ๋ฐ๊พธ๊ณ ์ด๋ฅผ ํ์ฉํ์ฌ ํด์ํ ์ด๋ธ์ ์ ๊ทผํด value๋ฅผ ๊ฐ์ ธ์ค๊ฑฐ๋, ์ ์ฅํ๋ ํํ๋ฅผ ๋งํจ
enum Flavor: String, CaseIterable, Identifiable { case chocolate, vanilla, strawberry var id: Self { self } } @State private var selectedFlavor: Flavor = .chocolate //Pikcer์ ๊ธฐ๋ณธ ์ธํ ๊ฐ์ @State๋ก ์ค์ ํ๋ค //์์ ์ด๊ฑฐํ ๊ฐ ์ค์์ ์ ํํ ์ ์๋ Picker ๋ง๋ค๊ธฐ //selection์ ์์ State๋ณ์๋ก ์ ์ธํ ๊ฐ์ ๋ฐ์ธ๋ฉํ์ฌ ๋ฃ๋๋ค List { Picker("Flavor", selection: $selectedFlavor) { Text("Chocolate").tag(Flavor.chocolate) Text("Vanilla").tag(Flavor.vanilla) Text("Strawberry").tag(Flavor.strawberry) } }
selectedFlavor
selection
tag
โ๏ธ๊ทผ๋ฐ ์ด ํ๊ทธ๊ฐ ๋จธํ๋ ์ค์ง ๋ชจ๋ฅด๊ฒ ์ ใ ใ โ ๋ค๋น๊ฒ์ด์ ํ ๋ ์ฐ๋ ๊ฑฐ ๊ฐ์
For each
Picker("Flavor", selection: $selectedFlavor) { ForEach(Flavor.allCases) { flavor in Text(flavor.rawValue.capitalized) } }
capitalized๋?
๋ฌธ์์ด์ ๋๋ฌธ์ ๊ฐ์ผ๋ก ํํํ ๊ฒ์ด๋ผ๊ณ ํจ
โ๏ธForeach๊ฐ ์๋์ผ๋ก ID ๊ฐ์ ํ์ฉํด tag๋ฅผ ํ ๋นํ๋ค๋๋ฐ โ Flavor๊ฐ ์๋ณ ๊ฐ๋ฅํ ํ๋กํ ์ฝ์ ์ค์ํ๊ธฐ ๋๋ฌธ์ด๋ผ๊ณ ํจโฆ์ด๊ฒ ๋ฌด์จ ๋ง..??
*์์ ์๋ Flavor๊ฐ ์ ํ ์ ํ๊ณผ ์ ํํ ์ผ์นํ๋๋ก id ๋งค๊ฐ๋ณ์์ ์ ํ์ ์ ์ํ๋ค๋ ์ฌ์ค์ ์์กดํ๋ค๊ณ ํจ. ๊ทธ๋ ์ง ์์ ๊ฒฝ์ฐ์๋ ํ๊ทธ๋ฅผ ์ฌ์ ์ํด์ผ ํจ!* โ **Foreach**
struct ForEach<Data, ID, Content> where Data : RandomAccessCollection, ID : Hashable
[PickerStyle | Apple Developer Documentation](https://developer.apple.com/documentation/swiftui/pickerstyle)
์ ํ์์๋ Picker์ ์คํ์ผ์ ์ปค์คํ ํ ์ ์๋๋ก PickerStyle ์ด๋ผ๋ ํ๋กํ ์ฝ์ ์ฌ์ฉํ๊ณ ์์!!
PickerStyle
VStack { Picker("Flavor", selection: $selectedFlavor) { ForEach(Flavor.allCases) { flavor in Text(flavor.rawValue.capitalized) } } Picker("Topping", selection: $selectedTopping) { ForEach(Topping.allCases) { topping in Text(topping.rawValue.capitalized) } } } .pickerStyle(.segmented)
๋ง์ฝ pickerStyle ์ .wheel ๋ก ํ๋ฉด vertical scrollํ๋ picker๊ฐ ์์ฑ!
pickerStyle
.wheel
์ผ๋จ Picker๋ฅผ ์ด๋ป๊ฒ ๋ง๋๋ ์ง๋ ์์์ ๋ฐฐ์ ๋๋ฐ, ์๋ ์ด๋ป๊ฒ ํด์ผํ์ง??
๊ณ ๋ฏผํด ๋ดค์ ๋!
์ด๋ ๊ฒ ์น์ ์ ๋๋์ด์ Picker 3๊ฐ๋ฅผ ๋ง๋ค์ด์ผํ ๊น?
import SwiftUI struct ContentView: View { var body: some View { @State var hour = 0 @State var minute = 0 @State var second = 0 var hours = [Int](0..<24) var minutes = [Int](0..<60) var seconds = [Int](0..<60) HStack { Picker(selection: $hour, label: Text("")){ ForEach(0..<24){ hour in Text("\(hours[hour]) ์๊ฐ").tag(hour) } } Picker(selection: $minute, label: Text("")){ ForEach(0..<60){ minute in Text("\(minutes[minute]) ๋ถ").tag(hour) } } Picker(selection: $second, label: Text("")){ ForEach(0..<60){ second in Text("\(seconds[second]) ์ด").tag(hour) } } }.pickerStyle(.wheel) .padding() } }
์ด๋ ๊ฒ ๋์ด;;ใ ใ
๊ตฌ๊ธ๋ง ํด๋ณด๋๊น
[Multi-Component Picker (UIPickerView) in SwiftUI](https://stackoverflow.com/questions/56567539/multi-component-picker-uipickerview-in-swiftui)
// // ContentView.swift // customPicker // // Created by ๊น์๋ฆผ on 7/28/24. // import SwiftUI struct PickerView: UIViewRepresentable { var data: [[String]] @Binding var selections: [Int] //makeCoordinator() func makeCoordinator() -> PickerView.Coordinator { Coordinator(self) } //makeUIView(context:) func makeUIView(context: UIViewRepresentableContext<PickerView>) -> UIPickerView { let picker = UIPickerView(frame: .zero) picker.dataSource = context.coordinator picker.delegate = context.coordinator return picker } //updateUIView(_:context:) func updateUIView(_ view: UIPickerView, context: UIViewRepresentableContext<PickerView>) { for i in 0...(self.selections.count - 1) { view.selectRow(self.selections[i], inComponent: i, animated: false) } context.coordinator.parent = self // fix } class Coordinator: NSObject, UIPickerViewDataSource, UIPickerViewDelegate { var parent: PickerView //init(_:) init(_ pickerView: PickerView) { self.parent = pickerView } //numberOfComponents(in:) func numberOfComponents(in pickerView: UIPickerView) -> Int { return self.parent.data.count } //pickerView(_:numberOfRowsInComponent:) func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { return self.parent.data[component].count } //pickerView(_:titleForRow:forComponent:) func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { return self.parent.data[component][row] } //pickerView(_:didSelectRow:inComponent:) func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { self.parent.selections[component] = row } } } import SwiftUI struct ContentView: View { private let data: [[String]] = [ Array(0...10).map { "\($0)" }, Array(20...40).map { "\($0)" }, Array(100...200).map { "\($0)" } ] @State private var selections: [Int] = [5, 10, 50] var body: some View { VStack { PickerView(data: self.data, selections: self.$selections) Text("\(self.data[0][self.selections[0]]) \(self.data[1][self.selections[1]]) \(self.data[2][self.selections[2]])") } //VStack } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } } #Preview { ContentView() }
[[SwiftUI] Picker ๋ง๋ณด๊ธฐ](https://sujinnaljin.medium.com/swiftui-picker-%EB%A7%9B%EB%B3%B4%EA%B8%B0-d745494f9a1c)
displayedComponents
// // ContentView.swift // customPicker // // Created by ๊น์๋ฆผ on 7/28/24. // import SwiftUI struct ContentView: View { @State var hour: Int @State var minute: Int var hours = [Int](0..<24) var minutes = [Int](0..<60) var body: some View { HStack(spacing: 0) { Picker("hours", selection: $hour) { ForEach (0..<24) { hour in Text("\(hours[hour])") } } .pickerStyle(.wheel) Text(":") .font(.title) .fontWeight(.heavy) Picker("hours", selection: $minute) { ForEach (0..<60) { minute in Text("\(minutes[minute])") } } .pickerStyle(.wheel) } .frame(width: 100, height: 100) } } #Preview { ContentView(hour: 0, minute: 0) }
Picker์ ์์ญ์ .frame ์ ํ์ฉํ์ฌ ์กฐ์ ํ ์ ์์
.frame
HStack์ .frame(width: 100, height: 100) ์ ๊ฑธ์ด์ ์กฐ์ ๊ฐ๋ฅ
.frame(width: 100, height: 100)
์ฌ๊ธฐ์ ๋์ด๋ฅผ .frame(width: 100, height: 50)๋ก ๋ ์ค์ด๋ฉด
.frame(width: 100, height: 50)
๋ค์๊ณผ ๊ฐ์ด ์์ญ์ด ๋ ์ค์ด๋ค๊ฒ ๋จ!
1. Picker๋?
label
,selectionValue
,content
๋ฅผ ํ์๋ก ํ๋ค.Hashable์ด๋?
์ฐ๋ฆฌ๊ฐ ์๋
dictionary
๋ key-value๋ก ๊ฐ์ ์ ์ฅํ๋๋ฐ, ์ด๋ฌํ ๋์ ๋๋ฆฌ๊ฐhash table
์ด๋ผ๋ ๊ฒ์ผ๋ก ๊ตฌํ๋์ด ์๋ค๊ณ ํจํด์ ํ ์ด๋ธ์ ๋ฐฐ์ด๋ก ๊ตฌํ์ด ๋์ด ์๋๋ฐ,
์ด๋ฐ ์์ผ๋ก key ๊ฐ์ ํด์ฑ ํจ์์ ๋ฃ์ด ํด์ํ์ฌ โ ๋ฐฐ์ด์ ์ฃผ์ ๊ฐ์ ์ป๊ณ , ๊ทธ ์ฃผ์๊ฐ์ ๋ง๋ index์ value ๊ฐ์ ์ ์ฅํ๋ค๊ณ ํจ. ์ด๋, ํด์ํ ์ด๋ธ์ ์์๋ฅผ ์งํค์ง ์๊ณ ์ ์ฅ ๋จ!!
๋ฐ๋ผ์ ๋ฐฐ์ด์ ์ ์ฅ๋ ๊ฐ์ ์๊ณ ์ถ๋ค๋ฉด, index ๊ฐ์ ์์์ผ ํ๋๋ฐ ์ด index ๊ฐ์ด ์์๋๋ก ๋์ด ์์ง ์๊ธฐ ๋๋ฌธ์ key ๊ฐ์ ์์์ผ ํ๋ ๊ฒ์ (์ฐ๋ฆฐ value๊ฐ ์ ์ฅ๋ ํด์ํ ์ด๋ธ์ index๋ฅผ ๋ชจ๋ฆ
โ ์ฆ Key๋ฅผ ํตํด ํด์ํ ์ด๋ธ์ index๋ฅผ ์์์ผ ํด๋น value์ ์ ๊ทผํ ์ ์๊ฒ ๋จ
๋ฐ๋ผ์ ํด์ํ ์ด๋ธ์ด๋ key ๋ผ๋ ๊ฒ์ ํด์ ํจ์๋ฅผ ์ด์ฉํด ์ฃผ์๊ฐ(index)๋ก ๋ฐ๊พธ๊ณ ์ด๋ฅผ ํ์ฉํ์ฌ ํด์ํ ์ด๋ธ์ ์ ๊ทผํด value๋ฅผ ๊ฐ์ ธ์ค๊ฑฐ๋, ์ ์ฅํ๋ ํํ๋ฅผ ๋งํจ
selectedFlavor
๋ผ๋ State๋ณ์๋ก ์ ์ธํ๋คselection
์ ์์ State๋ณ์๋ก ์ ์ธํ ๊ฐ์ ๋ฐ์ธ๋ฉํ์ฌ ๋ฃ๋๋คtag
๋ฅผ ์ถ๊ฐโ๏ธ๊ทผ๋ฐ ์ด ํ๊ทธ๊ฐ ๋จธํ๋ ์ค์ง ๋ชจ๋ฅด๊ฒ ์ ใ ใ โ ๋ค๋น๊ฒ์ด์ ํ ๋ ์ฐ๋ ๊ฑฐ ๊ฐ์
For each
์ฌ์ฉํด์ ๋ ๊ฐ๋จํ๊ฒ ๋ง๋ค๊ธฐ!capitalized๋?
๋ฌธ์์ด์ ๋๋ฌธ์ ๊ฐ์ผ๋ก ํํํ ๊ฒ์ด๋ผ๊ณ ํจ
โ๏ธForeach๊ฐ ์๋์ผ๋ก ID ๊ฐ์ ํ์ฉํด tag๋ฅผ ํ ๋นํ๋ค๋๋ฐ โ Flavor๊ฐ ์๋ณ ๊ฐ๋ฅํ ํ๋กํ ์ฝ์ ์ค์ํ๊ธฐ ๋๋ฌธ์ด๋ผ๊ณ ํจโฆ์ด๊ฒ ๋ฌด์จ ๋ง..??
๋ชจ๋ฅด๊ฒ ๋ ๋ถ๋ถ
2. StylingPickers
[PickerStyle | Apple Developer Documentation](https://developer.apple.com/documentation/swiftui/pickerstyle)
์ ํ์์๋ Picker์ ์คํ์ผ์ ์ปค์คํ ํ ์ ์๋๋ก
PickerStyle
์ด๋ผ๋ ํ๋กํ ์ฝ์ ์ฌ์ฉํ๊ณ ์์!!๋ง์ฝ
pickerStyle
์.wheel
๋ก ํ๋ฉด vertical scrollํ๋ picker๊ฐ ์์ฑ!3. Timer์ ์๋ Picker๋ ์ด๋ป๊ฒ ๋ง๋ค๊น?
์ผ๋จ Picker๋ฅผ ์ด๋ป๊ฒ ๋ง๋๋ ์ง๋ ์์์ ๋ฐฐ์ ๋๋ฐ, ์๋ ์ด๋ป๊ฒ ํด์ผํ์ง??
๊ณ ๋ฏผํด ๋ดค์ ๋!
์ด๋ ๊ฒ ์น์ ์ ๋๋์ด์ Picker 3๊ฐ๋ฅผ ๋ง๋ค์ด์ผํ ๊น?
์ด๋ ๊ฒ ๋์ด;;ใ ใ
๊ตฌ๊ธ๋ง ํด๋ณด๋๊น
[Multi-Component Picker (UIPickerView) in SwiftUI](https://stackoverflow.com/questions/56567539/multi-component-picker-uipickerview-in-swiftui)
Multi Component Picker ๊ตฌํํ๊ธฐ
[[SwiftUI] Picker ๋ง๋ณด๊ธฐ](https://sujinnaljin.medium.com/swiftui-picker-%EB%A7%9B%EB%B3%B4%EA%B8%B0-d745494f9a1c)
displayedComponents
๋ฅผ ํ์ฉํ ์๋ ์์ด ๋ณด์Picker์ ์์ญ์ ์กฐ์ ํ๋ ๋ฐฉ๋ฒ
Picker์ ์์ญ์
.frame
์ ํ์ฉํ์ฌ ์กฐ์ ํ ์ ์์HStack์
.frame(width: 100, height: 100)
์ ๊ฑธ์ด์ ์กฐ์ ๊ฐ๋ฅ์ฌ๊ธฐ์ ๋์ด๋ฅผ
.frame(width: 100, height: 50)
๋ก ๋ ์ค์ด๋ฉด๋ค์๊ณผ ๊ฐ์ด ์์ญ์ด ๋ ์ค์ด๋ค๊ฒ ๋จ!