iOS开发 - 国内城市选择控制器②

1.初始化或者搜索条为空时,表格显示所有数据

2.支持屏幕右边缘拼音首字母快速检索

2.搜索条不为空时,实时过滤显示

3.支持大小写拼音及中文搜索

支持闭包回传,所有东西都塞到一坨了,可以直接当个选择控制器使用..
代码有点混乱,看来也没时间继续优化节奏了,哥困了...

iOS开发 - 国内城市选择控制器②_第1张图片
Simulator Screen Shot 2016年6月24日 上午2.44.05

CityViewController.swift

import UIKit

class CityViewController: UIViewController {
    
    //闭包回传
    var selectCityBack: ((cityName: String) -> Void)?
    
    //MARK: - Property 属性
    var tableView:UITableView!
    let screen_W = UIScreen.mainScreen().bounds.size.width
    let screen_H = UIScreen.mainScreen().bounds.size.height
    
    let cityModel = CityDataModel()
    var cityModel_Key = [String]()
    
    //搜索状态
    enum SearchT {
        case on
        case off
    }
    var searchBar: UISearchBar?
    var searchRetrunData = [String]()
    var searchMode: SearchT = .off {
        didSet {
            self.changeTableViewData(searchMode)
        }
    }
    
    //MARK: - LifeCycle 生命周期
    override func viewDidLoad() {
        super.viewDidLoad()

        setupNavigationBar()
        setupCustomSearchView()
        setupTableView()
        
        searchMode = .off
    }
    
    //MARK: - ViewSetup 视图设置
    func setupNavigationBar()  {
        let navBarView = UIView(frame: CGRect(x: 0, y: 0, width: screen_W, height: 64))
        navBarView.backgroundColor = UIColor.whiteColor()
        self.view.addSubview(navBarView)
        
        let closeBtn = UIButton(type: .Custom)
        closeBtn.frame = CGRect(x: 20, y: 30, width: 40, height: 20)
        closeBtn.setTitle("关闭", forState: .Normal)
        closeBtn.setTitleColor(UIColor.orangeColor(), forState: .Normal)
        closeBtn.addTarget(self, action: #selector(CityViewController.closeButton), forControlEvents: .TouchUpInside)
        navBarView.addSubview(closeBtn)
        
        let titleLabel = UILabel(frame: CGRect(x: screen_W/2 - 50, y: 30, width: 100, height: 25))
        titleLabel.textColor = UIColor.blackColor()
        titleLabel.textAlignment = .Center
        titleLabel.font = UIFont.systemFontOfSize(15)
        titleLabel.text = "选择城市"
        navBarView.addSubview(titleLabel)
    }
    
    func setupCustomSearchView()  {
        searchBar = UISearchBar(frame: CGRect(x: 0, y: 64, width: screen_W, height: 40))
        searchBar?.placeholder = "请输入要搜索的城市"
        searchBar?.delegate = self
        self.view.addSubview(searchBar!)
    }
    
    func setupTableView() {
        tableView = UITableView(frame: CGRect(x: 0, y: 64 + 40 , width: screen_W, height: screen_H - 64), style: .Plain)
        self.view.addSubview(tableView)
        tableView.delegate = self
        tableView.dataSource = self
        tableView.sectionIndexColor = UIColor.orangeColor()
        //创建一个重用的单元格
        tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "Cell")
    }

    //MARK: - private 内部方法
    func changeTableViewData(searchMode: SearchT) {
        switch searchMode {
        case .off:
            cityModel_Key = self.cityModel.newdictK
        case .on:
            cityModel_Key = self.searchRetrunData
        }
        tableView.reloadData()
    }
    
   func closeButton()  {
        self.dismissViewControllerAnimated(true, completion: nil)
    }
}
//MARK: - UISearchBar 代理
extension CityViewController: UISearchBarDelegate {
    func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {
        
        //搜索栏为空时候,显示原来数据
        guard !searchText.isEmpty else { return self.searchMode = .off }
        
         //这里哥懒得做判断了,字母优先了
         let currsearchText = searchText.lowercaseString //转成小写字母
         var filterCity = cityModel.dictKey.filter{ $0.hasPrefix(currsearchText) }
            .flatMap{ CityDataModel.cityDic[$0] } //filter过滤  flatMap转换并去除nil
        
         if filterCity.isEmpty { //字母搜索结果为空时,使用文字搜索
            filterCity = cityModel.dictVaule.filter{ $0.hasPrefix(currsearchText) }
            }
         self.searchRetrunData = filterCity
         self.searchMode = .on
         print(searchRetrunData)
    }
    
    //按下右下角键
    func searchBarSearchButtonClicked(searchBar: UISearchBar) {
        searchBar.resignFirstResponder()
    }
    //滑动收起键盘
    func scrollViewDidScroll(scrollView: UIScrollView) {
        searchBar?.resignFirstResponder()
    }
}

//MARK: - UITableView 代理
extension CityViewController: UITableViewDelegate, UITableViewDataSource {
    
    // UITableViewDataSource
    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        guard case .off = searchMode else { return 1 }
        return cityModel_Key.count
    }
    
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        guard case .off = searchMode else { return cityModel_Key.count }
        
        let cityhead = cityModel_Key[section]
        return (cityModel.newdictKY[cityhead]?.count)!
    }
    
    func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        guard case .off = searchMode else { return nil }
        return cityModel_Key[section]
    }
    
    func sectionIndexTitlesForTableView(tableView: UITableView) -> [String]? {
        guard case .off = searchMode else { return nil }
        return cityModel_Key
    }
    
    func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        return 49
    }
    
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
        
        if searchMode == .on { //搜索状态 - 开
            cell.textLabel?.text = cityModel_Key[indexPath.row]
        } else {
            let cityhead = cityModel_Key[indexPath.section]
            let cityPinyin = cityModel.newdictKY[cityhead]![indexPath.row]
            cell.textLabel?.text = "\(CityDataModel.cityDic[cityPinyin]!)"
        }
        
        return cell
    }
    
    // UITableViewDelegate
    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        switch searchMode {
        case .off:
            let cityhead = cityModel_Key[indexPath.section]
            let cityPinyin = cityModel.newdictKY[cityhead]![indexPath.row]
            let currCtiy = CityDataModel.cityDic[cityPinyin]
            self.selectCityBack?(cityName: currCtiy!)
        case .on:
            let currCtiy = cityModel_Key[indexPath.row]
            self.selectCityBack?(cityName: currCtiy) //回传数据
        }
        self.dismissViewControllerAnimated(true, completion: nil)
    }
}

 // MARK: - 城市数据
 struct CityDataModel {
   static let cityDic = ["wuhai": "乌海", "chaoyang": "朝阳", "lanzhou": "兰州", "nanjing": "南京", "wuhan": "武汉", "hegang": "鹤岗", "yongzhou": "永州", "loudi": "娄底", "lianyungang": "连云港", "zhangzhou": "漳州", "zhumadian": "驻马店", "wuxi": "无锡", "chizhou": "池州", "shanghai": "上海", "shaoyang": "邵阳", "qiannan": "黔南", "zhongwei": "中卫", "tacheng": "塔城", "tonghua": "通化", "benxi": "本溪", "jingmen": "荆门", "cixi": "慈溪", "changsha": "长沙", "wanzhou": "万州", "jiyuan": "济源", "yanji": "延吉", "deyang": "德阳", "tangshan": "唐山", "changzhou": "常州", "meizhou": "梅州", "shijiazhuang": "石家庄", "yiwu": "义乌", "changchun": "长春", "linyi": "临沂", "shangyu": "上虞", "heihe": "黑河", "shannan": "山南", "fuxin": "阜新", "puyang": "濮阳", "changde": "常德", "changdu": "昌都", "ruian": "瑞安", "lijiang": "丽江", "wuzhou": "梧州", "tongliao": "通辽", "huaihua": "怀化", "ningbo": "宁波", "puer": "普洱", "kelamayi": "克拉玛依", "hanzhong": "汉中", "wuwei": "武威", "binzhou": "滨州", "guilin": "桂林", "nantong": "南通", "yongkang": "永康", "xiantao": "仙桃", "kezhou": "克州", "maoming": "茂名", "shuangyashan": "双鸭山", "changle": "长乐", "liyang": "溧阳", "suining": "遂宁", "huanggang": "黄冈", "huidong": "惠东", "honghe": "红河", "wulumuqi": "乌鲁木齐", "yangjiang": "阳江", "hainanzhou": "海南州", "hangzhou": "杭州", "jiangning": "江宁", "xuchang": "许昌", "tanggu": "塘沽", "zhanjiang": "湛江", "xuancheng": "宣城", "danyang": "丹阳", "chengde": "承德", "longyan": "龙岩", "sanxia": "三峡", "qiqihaer": "齐齐哈尔", "beijing": "北京", "huaian": "淮安", "jixi": "鸡西", "guiyang": "贵阳", "zhenjiang": "镇江", "nanchang": "南昌", "yaan": "雅安", "panzhihua": "攀枝花", "changxing": "长兴", "langfang": "廊坊", "guyuan": "固原", "mudanjiang": "牡丹江", "fuyang": "阜阳", "nanning": "南宁", "yili": "伊犁", "baotou": "包头", "dongying": "东营", "cangzhou": "沧州", "shantou": "汕头", "zhangjiajie": "张家界", "taiyuan": "太原", "jincheng": "晋城", "ali": "阿里", "qiandongnan": "黔东南", "yushu": "玉树", "dongguan": "东莞", "sanya": "三亚", "kunming": "昆明", "zhaoqing": "肇庆", "guangan": "广安", "daxinganling": "大兴安岭", "dali": "大理", "wuzhong": "吴忠", "xiaoshan": "萧山", "huizhou": "惠州", "jieyang": "揭阳", "luoyang": "洛阳", "baishan": "白山", "handan": "邯郸", "xingtai": "邢台", "jinan": "济南", "dandong": "丹东", "songyuan": "松原", "fuzhoufz": "抚州", "heze": "菏泽", "sanmenxia": "三门峡", "panjin": "盘锦", "yanan": "延安", "qingyuan": "清远", "aletai": "阿勒泰", "liaoyang": "辽阳", "shuozhou": "朔州", "qianxinan": "黔西南", "huadu": "花都", "yingkou": "营口", "haidong": "海东", "jiujiang": "九江", "suihua": "绥化", "kaifeng": "开封", "liuzhou": "柳州", "chuzhou": "滁州", "ankang": "安康", "shenzhen": "深圳", "yanbian": "延边", "zhangjiakou": "张家口", "bazhong": "巴中", "yixing": "宜兴", "mianyang": "绵阳", "hechi": "河池", "aba": "阿坝", "jian": "吉安", "yancheng": "盐城", "quanzhou": "泉州", "bengbu": "蚌埠", "chongzuo": "崇左", "dazhou": "达州", "baise": "百色", "panyu": "番禺", "luzhou": "泸州", "weinan": "渭南", "zigong": "自贡", "wulanchabu": "乌兰察布", "yantai": "烟台", "fushun": "抚顺", "haixi": "海西", "xianggang": "香港", "huaibei": "淮北", "huiyang": "惠阳", "guangzhou": "广州", "foshan": "佛山", "alashanmeng": "阿拉善", "qianan": "迁安", "shanwei": "汕尾", "yueyang": "岳阳", "zhongshan": "中山", "shizuishan": "石嘴山", "xiamen": "厦门", "boertala": "博尔塔拉", "xinzhou": "忻州", "hebi": "鹤壁", "tongchuan": "铜川", "zhoushan": "舟山", "emeishan": "峨眉山", "zhuozhou": "涿州", "lvliang": "吕梁", "qujing": "曲靖", "liaocheng": "聊城", "bijiediqu": "毕节", "huangshan": "黄山", "fuqing": "福清", "yangshuo": "阳朔", "suzhousz": "宿州", "tongling": "铜陵", "dehong": "德宏", "chifeng": "赤峰", "xiangtan": "湘潭", "weihai": "威海", "zhaotong": "昭通", "jinjiang": "晋江", "ningde": "宁德", "changzhi": "长治", "qinhuangdao": "秦皇岛", "luohe": "漯河", "haibei": "海北", "jiangmen": "江门", "bayannaoer": "巴彦淖尔", "qionghai": "琼海", "pingxiang": "萍乡", "jinhua": "金华", "lishui": "丽水", "chengdu": "成都", "anqing": "安庆", "xining": "西宁", "putian": "莆田", "linfen": "临汾", "huludao": "葫芦岛", "shenyang": "沈阳", "tongrendiqu": "铜仁", "linxia": "临夏", "zaozhuang": "枣庄", "qingdao": "青岛", "ezhou": "鄂州", "baoshan": "保山", "fuling": "涪陵", "xinyang": "信阳", "qitaihe": "七台河", "shihezi": "石河子", "dunhunag": "敦煌", "liuan": "六安", "linhai": "临海", "shaoxing": "绍兴", "daqing": "大庆", "changji": "昌吉", "anyang": "安阳", "deqing": "德清", "haerbin": "哈尔滨", "nanping": "南平", "shangqiu": "商丘", "jinchang": "金昌", "haining": "海宁", "zhangye": "张掖", "chenzhou": "郴州", "dongyang": "东阳", "chaozhou": "潮州", "zhangjiagang": "张家港", "xinyu": "新余", "huangnan": "黄南", "linzhi": "林芝", "longnan": "陇南", "hulunbeier": "呼伦贝尔", "naqu": "那曲", "jingzhou": "荆州", "yuyao": "余姚", "hezhou": "贺州", "shunde": "顺德", "laibin": "来宾", "meishan": "眉山", "baoji": "宝鸡", "leshan": "乐山", "suizhou": "随州", "tianjin": "天津", "yinchuan": "银川", "tieling": "铁岭", "laiwu": "莱芜", "chuxiong": "楚雄", "diqing": "迪庆", "haikou": "海口", "pingliang": "平凉", "siping": "四平", "ganzi": "甘孜", "hengyang": "衡阳", "xinganmeng": "兴安", "qinzhou": "钦州", "dingxi": "定西", "dezhou": "德州", "jiamusi": "佳木斯", "yulin": "玉林", "wenshan": "文山", "gannan": "甘南", "jiayuguan": "嘉峪关", "xiaogan": "孝感", "zhoukou": "周口", "yangzhou": "扬州", "wenzhou": "温州", "heyuan": "河源", "fangchenggang": "防城港", "hengshui": "衡水", "taizhoutz": "台州", "jiaozuo": "焦作", "beihai": "北海", "fuzhou": "福州", "lincang": "临沧", "aomen": "澳门", "shaoguan": "韶关", "yibin": "宜宾", "jinzhong": "晋中", "yingtan": "鹰潭", "nanyang": "南阳", "liupanshui": "六盘水", "qingyang": "庆阳", "jinzhou": "锦州", "liangshan": "凉山", "zhuzhou": "株洲", "datong": "大同", "leqing": "乐清", "anshan": "鞍山", "wenling": "温岭", "chaohu": "巢湖", "zunyi": "遵义", "shishi": "石狮", "xiangyang": "襄阳", "nujiang": "怒江", "baicheng": "白城", "wuan": "武安", "fuyangfy": "富阳", "wuhu": "芜湖", "hetian": "和田", "kunshan": "昆山", "yiyang": "益阳", "zhangqiu": "章丘", "guoluo": "果洛", "huangdao": "黄岛", "shiyan": "十堰", "hami": "哈密", "yichunyc": "伊春", "zhuhai": "珠海", "tulufan": "吐鲁番", "zibo": "淄博", "jiaxing": "嘉兴", "nanchong": "南充", "yichang": "宜昌", "yanzhou": "兖州", "taizhou": "泰州", "yichun": "宜春", "dalian": "大连", "xilinguolemeng": "锡林郭勒", "weifang": "潍坊", "guangyuan": "广元", "lasa": "拉萨", "chongqing": "重庆", "neijiang": "内江", "changshu": "常熟", "suzhou": "苏州", "eerduosi": "鄂尔多斯", "jining": "济宁", "yulinyl": "榆林", "maanshan": "马鞍山", "bozhou": "亳州", "rizhao": "日照", "yunfu": "云浮", "huainan": "淮南", "jilin": "吉林", "tongxiang": "桐乡", "shangrao": "上饶", "huangshi": "黄石", "ganzhou": "赣州", "quzhou": "衢州", "shangluo": "商洛", "kashi": "喀什", "wuyishan": "武夷山", "pingdingshan": "平顶山", "jingdezhen": "景德镇", "anshun": "安顺", "xian": "西安", "ziyang": "资阳", "sanming": "三明", "guigang": "贵港", "taicang": "太仓", "xianning": "咸宁", "huhehaote": "呼和浩特", "xishuangbanna": "西双版纳", "taian": "泰安", "rikaze": "日喀则", "xiangxi": "湘西", "baiyin": "白银", "jintan": "金坛", "baoding": "保定", "hefei": "合肥", "bazhou": "巴州", "jiangyin": "江阴", "xianyang": "咸阳", "jiuquan": "酒泉", "enshi": "恩施", "yuxi": "玉溪", "taibei": "台北", "xinxiang": "新乡", "xuzhou": "徐州", "conghua": "从化", "akesu": "阿克苏", "yangquan": "阳泉", "suqian": "宿迁", "zhengzhou": "郑州", "liaoyuan": "辽源", "huzhou": "湖州", "zhuji": "诸暨", "tianshui": "天水", "yuncheng": "运城"]
    
    //建立合适的数据模型 [section - [key: vaule]]
    var newdictKY = [String:[String]]()
    var newdictK:[String] { //排序后的 - 键
        return Array(newdictKY.keys).sort(<)
    }
    
    // 字典的键
    var dictKey:[String] {
        return Array(CityDataModel.cityDic.keys)
    }
    
    // 字典的值
    var dictVaule:[String] {
        return Array(CityDataModel.cityDic.values)
    }
    
    private var currStrHead = "a"
    private var currStrArr = [String]()
    init() {
        //建立排序规则
        let sortdeDictKey = dictKey.sort(<) //字典的键 - 升序
        for i in 0..

使用例子:
        let vc = CityViewController()
        self.presentViewController(vc, animated: true, completion: nil)
        vc.selectCityBack = ({(cityName: String) -> Void in
           // >> = cityName
        })

你可能感兴趣的:(iOS开发 - 国内城市选择控制器②)