在这一章中学习到了picker控件与collectionView视图,以下主要为普通picker的城市三级联动、collectionView视图使用的方法与对应DataSource和Delegate简单使用的Demo
picker控件:
import UIKit class FirstViewController: UIViewController,UITextFieldDelegate,UIPickerViewDelegate,UIPickerViewDataSource { //注:在使用Delegate或DataSource协议时,需要将对应控件指向当前视图 @IBOutlet weak var brithdayText: UITextField! //TextField 输出口 @IBOutlet weak var locationText: UITextField! //TextField 输出口 @IBOutlet weak var dataPicker: UIDatePicker! //DatePicker 输出口 @IBOutlet weak var pickerView: UIPickerView! //PickerView 输出口 @IBOutlet weak var buttonOk: UIButton! //Button 输出口 var pickerAllDatas = [String: AnyObject]() var pickerProvincesIndex: Int = 0 var pickerCitiesIndex: Int = 0 var pickerCountyIndex: Int = 0 //button点击事件 @IBAction func onclickOk(_ sender: UIButton) { if self.dataPicker.isHidden == false { //如果dataPicker是显示状态 //获取当前dataPicker选中的时间值 let theDate: NSDate = self.dataPicker.date as NSDate //日期本地化 theDate.description(with: NSLocale.current) //日期格式化 let dateFormatter: DateFormatter = DateFormatter() dateFormatter.dateFormat = "YYYY-MM-dd" //时间格式 YYYY-MM-dd HH:mm:ss //取得最终日期 let brithday = dateFormatter.string(from: theDate as Date) self.brithdayText.text = brithday //设置textField的值 }else if self.pickerView.isHidden == false { //如果pickerView是显示状态 let row1 = self.pickerView.selectedRow(inComponent: 0)//当前列的行索引 let row2 = self.pickerView.selectedRow(inComponent: 1)//当前列的行索引 let row3 = self.pickerView.selectedRow(inComponent: 2)//当前列的行索引 //设置textField的值 self.locationText.text = "\(self.provincesNmae(row: row1)) - \(self.citiesName(row: row2)) - \(self.countyName(row: row3))" } self.hiddenView()//隐藏规定的控件方法 } override func viewDidLoad() { super.viewDidLoad() self.hiddenView()//隐藏规定的控件方法 } //textField 单行文本输入框 [以下为协议委托的方法实现...] //开始输入时 func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { if textField.tag == 1 { self.dataPicker.isHidden = false //显示dataPicker self.pickerView.isHidden = true //隐藏pickerView self.brithdayText.text = "" //清空textfield的值 }else if textField.tag == 2 { self.dataPicker.isHidden = true //隐藏dataPicker self.pickerView.isHidden = false //显示pickerView self.locationText.text = "" //清空textfield的值 //获取plist文件路径 let plistPath = Bundle.main.path(forResource: "location", ofType: "plist") //获取属性列表文件中的全部数据保存到pickerAllDatas中 self.pickerAllDatas = NSDictionary(contentsOfFile: plistPath!) as! Dictionary //初始化省 市 县的索引 self.pickerProvincesIndex = 0 self.pickerCitiesIndex = 0 self.pickerCountyIndex = 0 //让省、市、县回到第一行 self.pickerView.selectRow(0, inComponent: 0, animated: false) self.pickerView.selectRow(0, inComponent: 1, animated: false) self.pickerView.selectRow(0, inComponent: 2, animated: false) //用户点击textField触发开始输入协议时,重新reloadComponent self.pickerView.reloadComponent(0) self.pickerView.reloadComponent(1) self.pickerView.reloadComponent(2) } self.buttonOk.isHidden = false //显示button return false //返回false不弹出键盘 } //实现协议UIPickerViewDataSource方法 //为选择器指定拨轮的个数 func numberOfComponents(in pickerView: UIPickerView) -> Int { return 3 } //为选择器中的某个拨轮指定行数 func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { if (component == 0) {//省 return self.pickerAllDatas.count }else if (component == 1) {//市 if self.pickerAllDatas.count == 0 {//如果pickerAllDatas没有数据 return 0 }else{//pickerAllDatas有数据则读取 let provincesString = self.provincesNmae(row: self.pickerProvincesIndex) return (self.pickerAllDatas[String(self.pickerProvincesIndex)]?[provincesString as Any] as! NSDictionary).count } }else if (component == 2) {//区 if self.pickerAllDatas.count == 0 { return 0 }else{ let provincesString = self.provincesNmae(row: self.pickerProvincesIndex) let citiesString = self.citiesName(row: self.pickerCitiesIndex) let citiesDict = (self.pickerAllDatas[String(self.pickerProvincesIndex)]?[provincesString as Any] as! NSDictionary)[String(self.pickerCitiesIndex)] as! NSDictionary return (citiesDict[citiesString as Any] as! NSArray).count } } return 0 } //实现协议UIPickerViewDelegate方法 //提供拨轮中的每一行的显示数据 func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { if component == 0 {//省 return self.provincesNmae(row: row) }else if component == 1 {//市 return self.citiesName(row: row) }else if component == 2 {//区 return self.countyName(row: row) } return "" } //点击拨轮中的行触发的事件 func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { if component == 0 {//省 self.pickerProvincesIndex = row self.pickerCitiesIndex = 0 self.pickerCountyIndex = 0 self.pickerView.reloadComponent(1) //重加载picker self.pickerView.reloadComponent(2) //重加载picker self.pickerView.selectRow(0, inComponent: 1, animated: true)//让市回到第一行且有动画效果 self.pickerView.selectRow(0, inComponent: 2, animated: true)//让县回到第一行且有动画效果 }else if component == 1 {//市 self.pickerCitiesIndex = row self.pickerCountyIndex = 0 self.pickerView.reloadComponent(2) ////重加载picker self.pickerView.selectRow(0, inComponent: 2, animated: true)//让县回到第一行且有动画效果 }else if component == 2 {//县 self.pickerCountyIndex = row } } /-------------------------------------------------------------------------*/ //根据索引得到 省 的名称 func provincesNmae(row: Int) ->String { return ((self.pickerAllDatas[String(row)] as AnyObject).allKeys[0] as? String)! } //根据索引得到 市 名称 func citiesName(row: Int) ->String { let provincesString = self.provincesNmae(row: self.pickerProvincesIndex) return (((self.pickerAllDatas[String(self.pickerProvincesIndex)]?[provincesString as Any] as! NSDictionary)[String(row)] as AnyObject).allKeys[0] as? String)! } //根据索引得到 县 名称 func countyName(row: Int) ->String { let provincesString = self.provincesNmae(row: self.pickerProvincesIndex) let citiesString = self.citiesName(row: self.pickerCitiesIndex) let citiesDict = (self.pickerAllDatas[String(self.pickerProvincesIndex)]?[provincesString as Any] as! NSDictionary)[String(self.pickerCitiesIndex)] as! NSDictionary let countArray = citiesDict[citiesString as Any] as! NSArray return (countArray[row] as? String)! } //隐藏规定的控件方法 func hiddenView() { self.buttonOk.isHidden = true //隐藏button self.dataPicker.isHidden = true //隐藏dataPicker self.pickerView.isHidden = true //隐藏pickerView } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } }
CollectionView视图:
import UIKit class CollectionViewController: UICollectionViewController { //以上在UICollectionViewController中包含UICollectionViewDataSource与UICollectionViewDelegate协议 //无需冗余引入,DataSource与Delegate也已经连线对应视图文件 @IBOutlet weak var showLabel: UILabel! var events: NSArray! override func viewDidLoad() { super.viewDidLoad() //获取plist文件路径 let plistPath = Bundle.main.path(forResource: "events", ofType: "plist") self.events = NSArray(contentsOfFile: plistPath!) } //数据源协议UICollectionViewDataSource的方法实现 //提供集合视图中节的个数,就是说有多少行 override func numberOfSections(in collectionView: UICollectionView) -> Int { return self.events.count / 2//如果不能整除需要在除后+1 } //提供某个节中的单元格个数,就是说每行有几列 override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return 2 } //为单元格提供显示需要的数据,必须实现的方法 override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { //使用可重用单元格标识获得一个可重用单元格对象,把超出屏幕的单元格对象拿来重用,可以节省内存 //此除的 “Cell” 为可重用单元格标识,需要在该集合视图中的cell中设定(可理解为collection下面cell的名字) let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! MyCollectionViewCell //以上MyCollectionViewCell为自定义的UICollectionViewCell的子类 //event为得到每一行中每一列的数据,indexPath.section为每一行的索引,indexPath.row每一条中列的索引 let event = self.events[indexPath.section 2 + indexPath.row] as! NSDictionary //以上拿到数据为字典,需要强转为 NSDictionary //取得数据到对应的控件中 cell.labelView.text = event["name"] as? String cell.imageView.image = UIImage(named: event["image"] as! String) return cell } //委托协议UICollectionViewDelegate的方法实现,方法有很多,这里只实现了选中单元格事件 override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { let event = self.events[indexPath.section 2 + indexPath.row] as! NSDictionary self.showLabel.text = event["name"] as? String //NSLog("select event name : %@", event["name"] as! String) } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } }