SwiftUI 中实现省市区选择器

效果如下

import SwiftUI

struct ContentView: View {
    @State private var addressItems: [Province] = []
    @State private var areas: [String] = []
    @State private var selectProvinceIndex = 0
    @State private var selectCityIndex = 0
    @State private var selectArea = ""
    private func loadAddress(){
        guard let addressFileUrl = Bundle.main.url(forResource: "Address", withExtension: "plist"), let data = try? Data(contentsOf: addressFileUrl) else{
            return
        }
        let result = try! PropertyListDecoder().decode([Province].self, from: data)

        self.addressItems = result
    }
    
    private func changeSelectAreas(selectCityIndex: Int){
        let selectedCity = self.addressItems[safe: selectProvinceIndex]?.cities[safe: selectCityIndex]
        if let areas = selectedCity?.areas{
            self.areas = areas
            self.selectArea = areas[safe: 0] ?? ""
        }
    }
    
    var body: some View {
        VStack{
            Text("province: \(addressItems[safe: selectProvinceIndex]?.ProvinceName ?? "未选择")"+",city: \(addressItems[safe: selectProvinceIndex]?.cities[safe: selectCityIndex]?.cityName ?? "未选择")"+",area:\(addressItems[safe: selectProvinceIndex]?.cities[safe: selectCityIndex]?.areas[safe: 0] ?? "未选择")")
            GeometryReader { geometry in
                HStack(spacing: 0){
                    Picker("", selection: $selectProvinceIndex) {
                        ForEach(0..<addressItems.count,id: \.self) {index in
                            Text(addressItems[index].ProvinceName)
                        }
                    }
                    .onChange(of: selectProvinceIndex, perform: { newValue in
                        self.selectCityIndex = 0
                        changeSelectAreas(selectCityIndex:0)
                    })
                    .frame(width: geometry.size.width/3, alignment: .center)
                    .clipped()
                    
                    Picker("", selection: $selectCityIndex) {
                        let cities = addressItems[safe: selectProvinceIndex]?.cities
                        if let cities = cities{
                            ForEach(0..<cities.count,id: \.self) {index in
                                Text(cities[safe: index]?.cityName ?? "")
                            }
                        }else{
                            EmptyView()
                        }
                    }
                    .onChange(of: selectCityIndex, perform: { newValue in
                        changeSelectAreas(selectCityIndex: newValue)
                    })
                    .frame(width: geometry.size.width/3, alignment: .center)
                    .clipped()
                    
                    Picker("", selection: $selectArea) {
                        
                        ForEach(areas,id: \.self) {
       
                            Text("\($0)")
                        }
                    }
                    .frame(width: geometry.size.width/3, alignment: .center)
                    .clipped()
                }
            }
        }.onAppear(perform: {loadAddress()})
    }

}

struct Province: Decodable{
    let  ProvinceName: String
    var cities: [City] = []
    enum CodingKeys: String, CodingKey{
        case ProvinceName = "province"
        case cities
    }
}

struct City: Decodable{
    
    let cityName: String
    var areas: [String] = []
    enum CodingKeys: String, CodingKey{
        case cityName = "city"
        case areas
    }
}

extension Collection{
    public subscript(safe index: Index) -> Element?{
        return indices.contains(index) ? self[index] : nil
    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Address.plist代码如下
首先创建一个Property.list文件,命名为Address

在Address.plist文件上右击open as ->Source Code

加入如下代码

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
	<dict>
		<key>province</key>
		<string>河北省</string>
		<key>cities</key>
		<array>
			<dict>
				<key>areas</key>
				<array>
					<string>长安区</string>
					<string>桥东区</string>
					<string>桥西区</string>
					<string>新华区</string>
					<string>井陉矿区</string>
					<string>裕华区</string>
					<string>井陉县</string>
					<string>正定县</string>
					<string>栾城县</string>
					<string>行唐县</string>
					<string>灵寿县</string>
					<string>高邑县</string>
					<string>深泽县</string>
					<string>赞皇县</string>
					<string>无极县</string>
					<string>平山县</string>
					<string>元氏县</string>
					<string>赵县</string>
					<string>辛集市</string>
					<string>藁城市</string>
					<string>晋州市</string>
					<string>新乐市</string>
					<string>鹿泉市</string>
                    <key>area</key>
                    <string>石家庄市</string>
				</array>
				<key>city</key>
				<string>长安区</string>
			</dict>
			<dict>
				<key>areas</key>
				<array>
					<string>路南区</string>
					<string>路北区</string>
					<string>古冶区</string>
					<string>开平区</string>
					<string>丰南区</string>
					<string>丰润区</string>
					<string>滦县</string>
					<string>滦南县</string>
					<string>乐亭县</string>
					<string>迁西县</string>
					<string>玉田县</string>
					<string>唐海县</string>
					<string>遵化市</string>
					<string>迁安市</string>
				</array>
				<key>city</key>
				<string>唐山市</string>
			</dict>
			<dict>
				<key>areas</key>
				<array>
					<string>海港区</string>
					<string>山海关区</string>
					<string>北戴河区</string>
					<string>青龙满族自治县</string>
					<string>昌黎县</string>
					<string>抚宁县</string>
					<string>卢龙县</string>
				</array>
				<key>city</key>
				<string>秦皇岛市</string>
			</dict>
			<dict>
				<key>areas</key>
				<array>
					<string>邯山区</string>
					<string>丛台区</string>
					<string>复兴区</string>
					<string>峰峰矿区</string>
					<string>邯郸县</string>
					<string>临漳县</string>
					<string>成安县</string>
					<string>大名县</string>
					<string>涉县</string>
					<string>磁县</string>
					<string>肥乡县</string>
					<string>永年县</string>
					<string>邱县</string>
					<string>鸡泽县</string>
					<string>广平县</string>
					<string>馆陶县</string>
					<string>魏县</string>
					<string>曲周县</string>
					<string>武安市</string>
				</array>
				<key>city</key>
				<string>邯郸市</string>
			</dict>
			<dict>
				<key>areas</key>
				<array>
					<string>桥东区</string>
					<string>桥西区</string>
					<string>邢台县</string>
					<string>临城县</string>
					<string>内丘县</string>
					<string>柏乡县</string>
					<string>隆尧县</string>
					<string>任县</string>
					<string>南和县</string>
					<string>宁晋县</string>
					<string>巨鹿县</string>
					<string>新河县</string>
					<string>广宗县</string>
					<string>平乡县</string>
					<string>威县</string>
					<string>清河县</string>
					<string>临西县</string>
					<string>南宫市</string>
					<string>沙河市</string>
				</array>
				<key>city</key>
				<string>邢台市</string>
			</dict>
			<dict>
				<key>city</key>
				<string>保定市</string>
				<key>areas</key>
				<array>
					<string>新市区</string>
					<string>北市区</string>
					<string>南市区</string>
					<string>满城县</string>
					<string>清苑县</string>
					<string>涞水县</string>
					<string>阜平县</string>
					<string>徐水县</string>
					<string>定兴县</string>
					<string>唐县</string>
					<string>高阳县</string>
					<string>容城县</string>
					<string>涞源县</string>
					<string>望都县</string>
					<string>安新县</string>
					<string>易县</string>
					<string>曲阳县</string>
					<string>蠡县</string>
					<string>顺平县</string>
					<string>博野县</string>
					<string>雄县</string>
					<string>涿州市</string>
					<string>定州市</string>
					<string>安国市</string>
					<string>高碑店市</string>
				</array>
			</dict>
			<dict>
				<key>city</key>
				<string>张家口市</string>
				<key>areas</key>
				<array>
                                        <string>桥东区</string>
                                        <string>桥西区</string>
                                        <string>宣化区</string>
                                        <string>下花园区</string>
                                        <string>宣化县</string>
                                        <string>张北县</string>
                                        <string>康保县</string>
                                        <string>沽源县</string>
                                        <string>尚义县</string>
                                        <string>蔚县</string>
                                        <string>阳原县</string>
                                        <string>怀安县</string>
                                        <string>万全县</string>
                                        <string>怀来县</string>
                                        <string>涿鹿县</string>
                                        <string>赤城县</string>
                                        <string>崇礼县</string>
				</array>
			</dict>
			<dict>
				<key>city</key>
				<string>秦皇岛市</string>
				<key>areas</key>
				<array>
                                        <string>海港区</string>
                                        <string>山海关区</string>
                                        <string>北戴河区</string>
                                        <string>青龙满族自治县</string>
                                        <string>昌黎县</string>
                                        <string>抚宁县</string>
                                        <string>卢龙县</string>
				</array>
			</dict>
			<dict>
				<key>city</key>
				<string>承德市</string>
				<key>areas</key>
				<array>
					<string>双桥区</string>
					<string>双滦区</string>
					<string>鹰手营子矿区</string>
					<string>承德县</string>
					<string>兴隆县</string>
					<string>平泉县</string>
					<string>滦平县</string>
					<string>隆化县</string>
					<string>丰宁满族自治县</string>
					<string>宽城满族自治县</string>
					<string>围场满族蒙古族自治县</string>
				</array>
			</dict>
			<dict>
				<key>city</key>
				<string>沧州市</string>
				<key>areas</key>
				<array>
					<string>新华区</string>
					<string>运河区</string>
					<string>沧县</string>
					<string>青县</string>
					<string>东光县</string>
					<string>海兴县</string>
					<string>盐山县</string>
					<string>肃宁县</string>
					<string>南皮县</string>
					<string>吴桥县</string>
					<string>献县</string>
					<string>孟村回族自治县</string>
					<string>泊头市</string>
					<string>任丘市</string>
					<string>黄骅市</string>
					<string>河间市</string>
				</array>
			</dict>
			<dict>
				<key>city</key>
				<string>廊坊市</string>
				<key>areas</key>
				<array>
					<string>安次区</string>
					<string>广阳区</string>
					<string>固安县</string>
					<string>永清县</string>
					<string>香河县</string>
					<string>大城县</string>
					<string>文安县</string>
					<string>大厂回族自治县</string>
					<string>霸州市</string>
					<string>三河市</string>
				</array>
			</dict>
			<dict>
				<key>city</key>
				<string>衡水市</string>
				<key>areas</key>
				<array>
					<string>桃城区</string>
					<string>枣强县</string>
					<string>武邑县</string>
					<string>武强县</string>
					<string>饶阳县</string>
					<string>安平县</string>
					<string>故城县</string>
					<string>景县</string>
					<string>阜城县</string>
					<string>冀州市</string>
					<string>深州市</string>
				</array>
			</dict>
		</array>
	</dict>
</array>
</plist>


posted @ 2021-07-21 11:29  我不爱吃鱼  阅读(582)  评论(1编辑  收藏  举报
Live2D