在这一章中学习到了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()
}
}