swift3.0 三级联动UIPickerView城市选择器

初学swift没几天,就试着自己写了一个城市选择器,纯swift代码。

ViewController.swift文件中:

//
//  ViewController.swift
//  swift demo - UIPickerView之城市选择器
//
//  Created by 柯其谱 on 17/3/11.
//  Copyright ? 2017年 柯其谱. All rights reserved.
//

import UIKit

//MARK: View life cycle
class ViewController: UIViewController {

    /** 懒加载的城市数据源数组 */
    fileprivate lazy var cCityDataArray: [StateModel] = {
        //Plist文件路径
        let path = Bundle.main.path(forResource: "area", ofType: "plist")
        var areas: NSArray? = nil
        //读取Plist文件数组
        if let arrayPath = path {
            areas = NSArray (contentsOfFile: arrayPath)
        }
        //数组转换为模型数组
        var cityData = Array<StateModel>()
        if let areasArr = areas {
            for area in areasArr {
                let areaDic = area as! NSDictionary
                let stateModel = StateModel.init(dictionary: areaDic)
                cityData.append(stateModel)
            }
        }
        return cityData
    }()

    /** 省级数据源数组 */
    fileprivate var cStatesArr: [StateModel]? = nil
    /** 市级数据源数组 */
    fileprivate var cCitiesArr: [CityModel]? = nil
    /** 区级数据源数组 */
    fileprivate var cAreasArr: [String]? = nil
    /** 选择城市的textField */
    fileprivate let cCityTextField: UITextField? = UITextField()
    /** 选择城市的pickerView */
    fileprivate let cCityPickerView: UIPickerView? = UIPickerView()
    /** 选择城市的toolBar */
    fileprivate let cCityToolBar: UIToolbar? = UIToolbar()
    /** 选择城市的背景蒙版 */
    fileprivate let cTextFieldCoverButton: UIButton = UIButton (frame: UIScreen.main.bounds)

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        self.view.backgroundColor = UIColor(red:0.85, green:0.85, blue:0.85, alpha:1.00)
        self.setupSubviews()
        //设置数据源数组初始值
        cStatesArr = cCityDataArray
        cCitiesArr = cStatesArr?.first?.cities
        cAreasArr = cCitiesArr?.first?.areas
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

//MARK: Setup
extension ViewController {
    /** 设置subviews */
    fileprivate func setupSubviews() -> Void {
        self.setupTextField()
        self.setupCoverButton()
        self.setupPickerView()
        self.setupToolBar()
    }

    /** 设置textField */
    private func setupTextField() -> Void {
        if let cityTextField = cCityTextField {
            cityTextField.frame = CGRect (x: 50, y: 200, width: 200, height: 44)
            cityTextField.delegate = self
            cityTextField.backgroundColor = UIColor.white
            cityTextField.placeholder = "请选择城市"
            cityTextField.borderStyle = UITextBorderStyle.roundedRect
            self.view.addSubview(cityTextField)
        }
    }

    /** 设置背景蒙版Button */
    private func setupCoverButton() -> Void {
        cTextFieldCoverButton.addTarget(self, action: #selector(clickTextFieldCoverButton(sender:)), for: UIControlEvents.touchUpInside)
        self.view.addSubview(cTextFieldCoverButton)
        cTextFieldCoverButton.isHidden = true
    }

    /** 设置pickerView */
    private func setupPickerView() -> Void {
        if let cityPickerView = cCityPickerView {
            cityPickerView.delegate = self
            cityPickerView.dataSource = self
            cCityTextField!.inputView = cityPickerView
        }
    }

    /** 设置toolBar */
    private func setupToolBar() -> Void {
        if let cityToolBar = cCityToolBar {
            cityToolBar.frame = CGRect (x: 0, y: 0, width: 0, height: 44)
            cityToolBar.backgroundColor = UIColor.white

            let cancelItem = UIBarButtonItem.init(title: "取消", style: UIBarButtonItemStyle.done, target: self, action: #selector(clickToolBarCancelItem(sender:)))
            let spaceItem = UIBarButtonItem.init(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
            let doneItem = UIBarButtonItem.init(title: "确定", style: UIBarButtonItemStyle.done, target: self, action: #selector(clickToolBarDoneItem(sender:)))
            cityToolBar.items = [cancelItem, spaceItem, doneItem]
            cCityTextField?.inputAccessoryView = cityToolBar
        }
    }
}

//MARK: UITextFieldDelegate
extension ViewController: UITextFieldDelegate {

    func textFieldDidBeginEditing(_ textField: UITextField) {
        cTextFieldCoverButton.isHidden = false
    }

    func textFieldDidEndEditing(_ textField: UITextField) {
        cTextFieldCoverButton.isHidden = true
    }
}

//MARK: UIPickerViewDelegate
extension ViewController: UIPickerViewDelegate, UIPickerViewDataSource {

    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 3
    }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        switch component {
        case 0:
            return cStatesArr!.count
        case 1:
            return cCitiesArr!.count
        case 2:
            return cAreasArr!.count
        default:
            return 0
        }
    }

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        switch component {
        case 0:
            return cStatesArr![row].state
        case 1:
            return cCitiesArr![row].city
        case 2:
            return cAreasArr![row]
        default:
            return nil
        }
    }

    func pickerView(_ pickerView: UIPickerView, widthForComponent component: Int) -> CGFloat {
        return self.view.frame.width / 3
    }

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        switch component {
        case 0:
            //保存市级数据源数组
            cCitiesArr = cCityDataArray[row].cities
            //若有区级数据,则保存区级数据源数组
            if cCitiesArr?.first?.areas != nil {
                cAreasArr = cCitiesArr?.first?.areas
            }

            //重新加载第1、2组
            pickerView.reloadComponent(1)
            pickerView.reloadComponent(2)

            //默认选中第1、2组的第1行数据
            pickerView.selectRow(0, inComponent: 1, animated: true)
            pickerView.selectRow(0, inComponent: 2, animated: true)
        case 1:
            //保存区级数据源数组
            if cCitiesArr![row].areas.count != 0 {
                cAreasArr = cCitiesArr![row].areas
            }

            //重新加载第2组数据
            pickerView.reloadComponent(2)

            //默认选中第2组第1行数据
            pickerView.selectRow(0, inComponent: 2, animated: true)
        default:
            return
        }
    }
}

//MARK: Event response
extension ViewController {
    @objc fileprivate func clickTextFieldCoverButton(sender: UIButton) -> Void {
        cCityTextField?.resignFirstResponder()
    }

    @objc fileprivate func clickToolBarCancelItem(sender: UIBarButtonItem) -> Void {
        cCityTextField?.resignFirstResponder()
    }

    @objc fileprivate func clickToolBarDoneItem(sender: UIBarButtonItem) -> Void {
        cCityTextField?.resignFirstResponder()
        let selectedState = cCityPickerView?.selectedRow(inComponent: 0)
        let selectedCity = cCityPickerView?.selectedRow(inComponent: 1)
        let selectedArea = cCityPickerView?.selectedRow(inComponent: 2)
        var cityString = (cStatesArr?[selectedState!].state)! + (cCitiesArr?[selectedCity!].city)!
        if cAreasArr?.count != 0 {
            cityString += (cAreasArr?[selectedArea!])!
        }
        cCityTextField?.text = cityString
    }
}

StateModel.swfit文件中,用于保存省级数据:

//
//  StateModel.swift
//  swift demo - UIPickerView之城市选择器
//
//  Created by 柯其谱 on 17/3/11.
//  Copyright ? 2017年 柯其谱. All rights reserved.
//

import UIKit

/** 省级Model */
class StateModel: NSObject {

    /** 省下级所有城市 */
    let cities: Array<CityModel>

    /** 省级名称 */
    let state: String

    init(dictionary: NSDictionary) {
        state = dictionary["state"] as! String
        let citiesArr = dictionary["cities"] as! NSArray
        var citiesMutableArr = Array<CityModel>()
        for city in citiesArr {
            let cityDic = city as! NSDictionary
            let cityModel = CityModel.init(dictionary: cityDic)
            citiesMutableArr.append(cityModel)
        }
        cities = citiesMutableArr
    }
}

CityModel.swift文件中,用于保存市级数据

//
//  CityModel.swift
//  swift demo - UIPickerView之城市选择器
//
//  Created by 柯其谱 on 17/3/11.
//  Copyright ? 2017年 柯其谱. All rights reserved.
//

import UIKit

//MARK: 城市Model
class CityModel: NSObject {

    /** 城市下级area */
    let areas: Array<String>
    /** 城市名 */
    let city: String

    init(dictionary: NSDictionary){
        city = dictionary["city"] as! String
        let areasArr = dictionary["areas"] as! NSArray
        var areasMutableArr = Array<String>()
        for area in areasArr {
            let areaString = area as! String
            areasMutableArr.append(areaString)
        }
        areas = areasMutableArr
    }

}
时间: 2024-12-29 15:59:27

swift3.0 三级联动UIPickerView城市选择器的相关文章

Android 三级联动选择城市+后台服务加载数据库

技术渣,大家将就着看 首先我们需要一个xml数据保存到数据库,这里我从QQ下面找到一个loclist.xml文件 <CountryRegion Name="中国" Code="1"> <State Name="北京" Code="11"> <City Name="东城" Code="1" /> <City Name="西城"

三级联动显示城市列表

<div class="select"> <select id="prv" ></select> <select id="city" ></select> <select id="county" ></select></div> <script> var id1=0; var id2=0; //对应省份下的地址数据获取

ASP.NET Web Form服务器控件三级联动

<form id="form1" runat="server"> <asp:ScriptManager ID="ScriptManager1" runat="server"> </asp:ScriptManager> <asp:UpdatePanel ID="UpdatePanel1" runat="server" style="dis

Android城市三级联动选择器

便捷.新颖的三级fdsafdsa联动城市选择器 /**  * 城市Picker  *  * @author zihao  *  */ public class CityPicker extends LinearLayout {     /** 滑动控件 */fdsaf     private ScrollerNumberPicker provincePicker;     private ScrollerNumberPicker cityPicker;     private ScrollerN

时间和地域三级联动选择器(Android-PickerView-master)

先附上下载和效果展示地址 https://github.com/saiwu-bigkoo/Android-PickerView 之后说一下程序依赖后会遇到的问题Error:(2, 0) Plugin with id 'com.github.dcendents.android-maven' not found. 解决办法在Project下的build.gradle中添加两句 classpath 'com.github.dcendents:android-maven-gradle-plugin:1.

记录 vant Picker 选择器,实现三级联动,传对应省市区code值

最近使用vant UI写移动端,感觉还不错 功能挺全的,带的还有省市区三级联动. 但是 突然遇到一个 产品要传的 省市区的code码,还和vant的 邮编不一样,我*****. 看了一下vant UI提供的api有提供 Picker 选择器的api,哇,心里美滋滋,但是我api提供的只有二级联动,我****,没事凭我的本事,琢磨个一两个月还不是问题的,哈哈. vant Picker 选择器 开始======================> 首先看一下接口返回的数据结构吧,省市区三级联动,每一级

jquery 城市三级联动

js代码 /*城市三级联动 * @method cityChange * @param allProvince,allCity,allDistrict */ function cityChange(provinceN,cityN,districtN){ var all_province=""; for(var i=0;i<allCity.province.length;i++){ all_province+='<option name="province"

转: javascript实现全国城市三级联动菜单代码

<html> <head> <title>js全国城市三级联动菜单代码_B5教程网</title> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> <script LANGUAGE="JavaScript"> function Dsy() { this.Items = {}; } Dsy

UIPickerView实现省 市 区三级联动

前几天用UIPickerView实现了一下三级联动具体的如下图 下面是实现方式 #import "ViewController.h" #define FirstComponent 0 #define SubComponent 1 #define ThirdComponent 2 @interface ViewController () @property(nonatomic,retain)NSDictionary* dict; @property(nonatomic,retain)NS