初学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
}
}