Swift iOS数据源协议、委托协议与高级视图

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

编程工人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值