本文實(shí)例為大家分享了swift實(shí)現(xiàn)ipad版美團(tuán)界面功能的具體代碼,供大家參考,具體內(nèi)容如下
一 總體功能圖一 : (ipad豎屏)
二 總體功能圖二 : (ipad橫屏)
三 講解內(nèi)容
1 搭建美團(tuán)界面(掌握)
2 ios8.0之后的Popover的運(yùn)用(重點(diǎn))
3 協(xié)議(掌握)
4 通知(掌握)
5 細(xì)節(jié)處理
四總體界面
1 由總體的app界面效果,能看出來(lái),一個(gè)UIViewController控制器作為UINavigationController的根控制器就能滿足條件.
五 導(dǎo)航條設(shè)置
1 自定義導(dǎo)航條 : (系統(tǒng)的導(dǎo)航條不能滿足需求)
2 創(chuàng)建導(dǎo)航控制器類(lèi)
3 獲取全局的導(dǎo)航條 : (用來(lái)作為設(shè)置)
//獲取導(dǎo)航條let navigationBar = UINavigationBar.appearanceWhenContainedInInstancesOfClasses([self.classForCoder])
3.1 注意 :一定要用上面的方法來(lái)獲取,不要用下面的方法來(lái)獲取,因?yàn)橥ㄟ^(guò)下面方法獲取對(duì)導(dǎo)航條的設(shè)置,很有可能會(huì)造成導(dǎo)航條呈現(xiàn)黑色的情況.
UINavigationBar.appearance()
4 用圖片包裝導(dǎo)航條
//設(shè)置導(dǎo)航條的樣式navigationBar.setBackgroundImage(UIImage(named: "bg_navigationBar_normal"), forBarMetrics: .Default)
5 注意不要忘了將導(dǎo)航控制器的類(lèi)型改為自定義類(lèi)型,否則會(huì)加載不出來(lái)的
六 導(dǎo)航條相關(guān)內(nèi)容處理
1 思路 : 通過(guò)觀察導(dǎo)航條中的按鈕,我們可以看出, 按鈕都是由圖片;主標(biāo)題;子標(biāo)題組成的,所以我們可以通過(guò)xib來(lái)描述,并且用一個(gè)UIView將按鈕包裹住,方便修改設(shè)置
2 創(chuàng)建繼承UIView的類(lèi),同時(shí)創(chuàng)建同類(lèi)名的xib
3 xib圖
4 xib內(nèi)部分布結(jié)構(gòu)圖
5 如何在xib中分離圖片和標(biāo)題之間的距離? 5.1 下圖解答
6 通過(guò)給xib拖線,拿到內(nèi)部屬性
//按鈕頭像 @IBOutlet weak var iconButton: UIButton!//頭部子標(biāo)題 @IBOutlet weak var subtitleLabel: UILabel!//頭部標(biāo)題 @IBOutlet weak var title_Label: UILabel!
7 給xib中的屬性提供set方法和對(duì)應(yīng)的get方法,方便外邊調(diào)用修改
//對(duì)頭部標(biāo)題提供Set方法 var title : String? { didSet{ return title_Label.text = title } } //對(duì)頭部子標(biāo)題提供set方法 var subtitle : String? { didSet{ return subtitleLabel.text = subtitle } } //對(duì)按鈕頭像提供set方法(平常的圖片) var normalName : String? { didSet{ return iconButton.setImage(UIImage(named: normalName!), forState: .Normal) } } //對(duì)按鈕頭像提供set方法(點(diǎn)擊后的圖片) var heightName : String? { didSet{ return iconButton.setImage(UIImage(named: heightName!), forState: .Highlighted) } } //對(duì)按鈕提供一個(gè)get方法 var getIconButton : UIButton { get{ return iconButton } }
8 提供一個(gè)加載xib的類(lèi)方法,讓外界能通過(guò)該方法快速創(chuàng)建xib
//MARK: - 給類(lèi)擴(kuò)展一個(gè)方法(加載xib)extension XFJTopView { //提供一個(gè)快速創(chuàng)建xib的類(lèi)方法 class func topView(title : String, subTitle : String, normalImageName : String, heightImageName : String) ->XFJTopView { let topView = NSBundle.mainBundle().loadNibNamed("XFJTopView", owner: nil, options: nil).last! as! XFJTopView //給屬性賦值 topView.title_Label.text = title topView.subtitleLabel.text = subTitle topView.iconButton.setImage(UIImage(named: normalImageName), forState: .Normal) topView.iconButton.setImage(UIImage(named: heightImageName), forState: .Highlighted) //返回通過(guò)xib創(chuàng)建的對(duì)象 return topView }}
9 添加頂部的按鈕
—-> 9.1 思路 : 通過(guò)添加到由導(dǎo)航條管理的item中的數(shù)組中來(lái)實(shí)現(xiàn)對(duì)加載xib的時(shí)候按鈕的添加
—-> 9.2 導(dǎo)航控制器的根控制器
—-> 9.3 XFJHomeViewController類(lèi)對(duì)導(dǎo)航條中的item的管理(該部分代碼比較多,我們通過(guò)類(lèi)擴(kuò)展來(lái)實(shí)現(xiàn))
//MARK: - 設(shè)置導(dǎo)航條中的itemextension XFJHomeViewController { @objc private func setUpTabBarItem() { //設(shè)置值item的圖片(0) let logoItem = UIBarButtonItem(image: UIImage(named: "icon_meituan_logo"), style: .Plain, target: nil, action: nil) //對(duì)導(dǎo)航條最左邊的item賦值 navigationItem.leftBarButtonItem = logoItem //取消導(dǎo)航條左邊的item點(diǎn)擊 logoItem.enabled = false //設(shè)置其他的items(一) let item1 = XFJTopView.topView("美團(tuán)", subTitle: "全部分類(lèi)", normalImageName: "icon_category_-1", heightImageName: "icon_category_highlighted_-1") //設(shè)置第一個(gè)item let topItem = UIBarButtonItem(customView: item1) //對(duì)按鈕的監(jiān)聽(tīng) item1.getIconButton.addTarget(self, action: "presentPopTopViewClick", forControlEvents: .TouchUpInside) //賦值 self.topItem = topItem //設(shè)置items(二) let item2 = XFJTopView.topView("廣州", subTitle: "全部", normalImageName: "icon_district", heightImageName: "icon_district_highlighted") let gzItem = UIBarButtonItem(customView: item2) item2.getIconButton.addTarget(self, action: "presentPopGzViewClick", forControlEvents: .TouchUpInside) //賦值 self.gzItem = gzItem //設(shè)置items(三) let item3 = XFJTopView.topView("排序", subTitle: "默認(rèn)排序", normalImageName: "icon_sort", heightImageName: "icon_sort_highlighted") let sortItem = UIBarButtonItem(customView: item3) item3.getIconButton.addTarget(self, action: "presentPopSortViewClick", forControlEvents: .TouchUpInside) //賦值 self.sortItem = sortItem //將item添加到數(shù)組中 navigationItem.leftBarButtonItems = [logoItem,topItem,gzItem,sortItem] }}
七 Popover的彈出
1 分別創(chuàng)建三個(gè)類(lèi)來(lái)管理彈出的Popover
2 對(duì)頂部三個(gè)item所彈出的控制做懶加載創(chuàng)建,保證用到的時(shí)候在創(chuàng)建
//MARK: - 懶加載控制器(一) private lazy var categoryVC : XFJCategoryViewController = { //創(chuàng)建控制器 let categoryVC = XFJCategoryViewController() //設(shè)置控制器的樣式 categoryVC.modalPresentationStyle = .Popover //返回控制器 return categoryVC }() //MARK: - 懶加載控制器(二) private lazy var districtVC : XFJDistrictViewController = { //創(chuàng)建控制器 let districtVC = XFJDistrictViewController() //設(shè)置控制器的樣式 districtVC.modalPresentationStyle = .Popover //返回控制器 return districtVC }() //MARK: - 懶加載控制器(三) private lazy var sortsVC : XFJSortsViewController = { //創(chuàng)建控制器 let sortsVC = XFJSortsViewController() //設(shè)置控制器的樣式 sortsVC.modalPresentationStyle = .Popover //返回控制器 return sortsVC }()
3 根據(jù)彈出的Popover類(lèi)型,我們也可以看出是由兩個(gè)UITableView組成,并且各占控制器的一半,那么我們這部分也可以通過(guò)xib來(lái)實(shí)現(xiàn).
—-> 3.1 創(chuàng)建一個(gè)類(lèi)來(lái)管理,同時(shí)創(chuàng)建xib
3.2 xib內(nèi)部圖
4 彈出Popover(通過(guò)在9.3中對(duì)item的監(jiān)聽(tīng))
—-> 4.1 彈出Popover代碼塊一 :
//MARK : - 實(shí)現(xiàn)監(jiān)聽(tīng)方法extension XFJHomeViewController { @objc private func presentPopTopViewClick() { //彈出位置 categoryVC.popoverPresentationController?.barButtonItem = topItem //設(shè)置背景顏色 categoryVC.popoverPresentationController?.backgroundColor = UIColor.clearColor() //model出控制器 presentViewController(categoryVC, animated: true, completion: nil) //取消UIBarButtonItem的交互 setDisabled() //設(shè)置代理 categoryVC.popoverPresentationController?.delegate = self }}
—-> 4.1 彈出Popover代碼塊二:
extension XFJHomeViewController { @objc private func presentPopGzViewClick() { //彈出位置 districtVC.popoverPresentationController?.barButtonItem = gzItem //設(shè)置背景顏色 districtVC.popoverPresentationController?.backgroundColor = UIColor.clearColor() // //model出控制器 presentViewController(districtVC, animated: true, completion: nil) //取消UIBarButtonItem的交互 setDisabled() //設(shè)置代理 districtVC.popoverPresentationController?.delegate = self }}
—-> 4.1 彈出Popover代碼塊三 :
extension XFJHomeViewController { @objc private func presentPopSortViewClick() { //彈出控制器的位置 sortsVC.popoverPresentationController?.barButtonItem = sortItem //設(shè)置背景顏色 sortsVC.popoverPresentationController?.backgroundColor = UIColor.whiteColor() //model出控制器 presentViewController(sortsVC, animated: true, completion: nil) //取消UIBarButtonItem的交互 setDisabled() //設(shè)置代理 sortsVC.popoverPresentationController?.delegate = self }}
八 處理彈出的Popover相關(guān)數(shù)據(jù)(全部由對(duì)應(yīng)的模型來(lái)決定)
1 獲取xib中的對(duì)象并且提供一個(gè)快速創(chuàng)建xib的類(lèi)方法
//左邊的tableView @IBOutlet weak var leftTableView: UITableView! //右邊的tableView @IBOutlet weak var rightTableView: UITableView! //模型分類(lèi)數(shù)據(jù) var categories : [XFJCategories]? //地區(qū)模塊的數(shù)據(jù) var DistrictData : [XFJDistrict]? //定義一個(gè)屬性,用來(lái)記錄用戶點(diǎn)擊了左側(cè)的哪一行 var seletIndex : Int? //快速創(chuàng)建xib的類(lèi)方法 class func lrTableView() ->XFJLRTableView { return NSBundle.mainBundle().loadNibNamed("XFJLRTableView", owner: nil, options: nil).last as! XFJLRTableView } //分類(lèi)的子數(shù)據(jù) private var subData : [String]?
2 通過(guò)在xib中設(shè)置代理和數(shù)據(jù)源實(shí)現(xiàn)有關(guān)數(shù)據(jù)源方法
—-> 2.1 數(shù)據(jù)源方法一 : cell的個(gè)數(shù)
//MARK: - 數(shù)據(jù)源方法extension XFJLRTableView : UITableViewDataSource { //cell的個(gè)數(shù) func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { //判斷是左邊還是右邊 if tableView == leftTableView { //左邊 return (delegateSource?.numberOfRowsInLeft(self))! }else{ //右邊 return subData?.count ?? 0 } }
—-> 2.2 數(shù)據(jù)源方法二 : cell的內(nèi)容
//cell的內(nèi)容 func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { //創(chuàng)建cell var cell = UITableViewCell?() //判斷 if tableView == leftTableView { //創(chuàng)建自定義cell cell = XFJLeftViewCell.leftViewCell(tableView) //設(shè)置文字 cell?.textLabel?.text = delegateSource?.lrTableView(titleDataSource: indexPath.row) //設(shè)置頭像(平常圖)--注意 :lrTableViewWithNormalImageInLeft千萬(wàn)要注意大小寫(xiě) if delegate?.respondsToSelector("lrTableViewWithNormalImageInLeft:") == true { cell?.imageView?.image = UIImage(named: (delegateSource?.lrTableView!(normalImageInLeft: indexPath.row))!) } //設(shè)置頭像(高亮圖)--注意 :lrTableViewWithHighlightImageLeft千萬(wàn)要注意大小寫(xiě) if delegate?.respondsToSelector("lrTableViewWithHighlightImageLeft:") == true { cell?.imageView?.highlightedImage = UIImage(named: (delegateSource?.lrTableView!(highlightImageLeft: indexPath.row))!) } }else{ cell = XFJRightViewCell.righViewCell(tableView) //設(shè)置內(nèi)容 cell?.textLabel?.text = subData![indexPath.row] } return cell! }
—-> 2.3 數(shù)據(jù)源方法三 : 點(diǎn)擊cell做出的相應(yīng)數(shù)據(jù)改變
//MARK: - 點(diǎn)擊左邊的cellextension XFJLRTableView : UITableViewDelegate { func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { //判斷是否是左邊 if tableView == leftTableView {//左邊 //獲取子數(shù)據(jù) subData = delegateSource?.lrTableView(subDataSource: indexPath.row) //調(diào)用協(xié)議方法(傳入用戶點(diǎn)擊的哪行) delegate?.lrTableView(seletLeftButton: indexPath.row) //記錄用戶點(diǎn)擊了左側(cè)的哪行 seletIndex = indexPath.row //刷新表格 rightTableView.reloadData() }else{ //右邊 //調(diào)用協(xié)議方法,傳入右側(cè)點(diǎn)擊了哪行和左側(cè)選中了哪行 delegate?.lrTableView(seletRightButton: indexPath.row, seletLeftButton: seletIndex!) } }}
九 創(chuàng)建模型
1 導(dǎo)入plist文件
2 創(chuàng)建繼承NSObject的類(lèi),用來(lái)設(shè)置需要用到的模型屬性
-> 2.1 模型屬性一 :(分類(lèi)中所需要的模型屬性)
var highlighted_icon = String?() var icon = String?() var name = String?() var small_highlighted_icon = String?() var small_icon = String?() var map_icon = String?() var subcategories = [String]?()
—-> 2.2 模型屬性二 : (全部模塊中所需要的模型屬性)
var name = String?() var subregions = [String]?()
—-> 2.3 模型屬性三 : (排序模塊中所需要的模型屬性)
var label = String?() var value = Int?()
3 在各自管理的類(lèi)中懶加載模型(采用MJ框架加載模型)
—-> 3.1 分類(lèi)模塊中懶加載模型
//懶加載模型 private lazy var categories : [XFJCategories] = { let categoriesData = XFJCategories.objectArrayWithFilename("categories.plist") as NSArray //返回模型 return categoriesData as! [XFJCategories] }()
—-> 3.2 地區(qū)模塊中懶加載模型
//懶加載 private lazy var DistrictView :[XFJDistrict] = { let DistrictData = XFJDistrict.objectArrayWithFilename("gz.plist") as NSArray //返回模型數(shù)據(jù) return DistrictData as! [XFJDistrict] }()
—-> 3.3 排序模塊中懶加載模型
//創(chuàng)建一個(gè)屬性記錄按鈕的點(diǎn)擊狀態(tài) var previousButton = UIButton() //懶加載 private lazy var sortsData : [XFJSorts] = { //模型轉(zhuǎn)化 let sortsDatas = XFJSorts.objectArrayWithFilename("sorts.plist") as NSArray //返回模型 return sortsDatas as! [XFJSorts] }()
十 自定義cell
1 通過(guò)功能圖知道Popover出來(lái)的控制器中cell中既展示圖片又展示文字,所以我們通過(guò)自定義cell來(lái)設(shè)置 2 自定義左邊的tableViewCell
class XFJLeftViewCell: UITableViewCell { //左邊的tableView class func leftViewCell(tableView : UITableView) ->XFJLeftViewCell { //綁定cell類(lèi)型 let leftCell = "leftCell" var cell = tableView.dequeueReusableCellWithIdentifier(leftCell) //判斷cell是否為空 if cell == nil { cell = XFJLeftViewCell(style: .Default, reuseIdentifier: leftCell) } return cell as! XFJLeftViewCell } override init(style: UITableViewCellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) //設(shè)置背景圖片 backgroundView = UIImageView(image: UIImage(named:"bg_dropdown_leftpart")) selectedBackgroundView = UIImageView(image: UIImage(named:"bg_dropdown_left_selected")) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") }}
2.1 該方法是在數(shù)據(jù)源方法中調(diào)用的,用來(lái)加載cell
3 自定義右邊的tableViewCell
class XFJRightViewCell: UITableViewCell { //右邊的tableView class func righViewCell(tableView : UITableView) ->XFJRightViewCell { //定義cell的標(biāo)識(shí) let rightCell = "rightCell" //創(chuàng)建cell var cell = tableView.dequeueReusableCellWithIdentifier(rightCell) //判斷 if cell == nil { cell = XFJRightViewCell(style: .Default, reuseIdentifier: rightCell) } //返回cell return cell as! XFJRightViewCell } //設(shè)置cell的背景圖片 override init(style: UITableViewCellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) backgroundView = UIImageView(image: UIImage(named: "bg_dropdown_rightpart")) selectedBackgroundView = UIImageView(image: UIImage(named:"bg_dropdown_right_selected")) } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") }}
十一 上半部分總結(jié)
1 用上面這些方法確實(shí)可以達(dá)到用戶點(diǎn)擊item,彈出對(duì)應(yīng)的控制器.但是上面的代碼只是寫(xiě)了對(duì)其中一個(gè)點(diǎn)擊item彈出的業(yè)邏輯,還有中間的item并沒(méi)與處理,如果采用這樣的方法處理,那么代碼量太多了,并且看起來(lái)也顯得沒(méi)什么技術(shù)含量,我們最終將不會(huì)采用這種方法實(shí)現(xiàn).
十二 代理 協(xié)議(最終實(shí)現(xiàn)的方案)
1 需要實(shí)現(xiàn)的功能 : 通過(guò)代理協(xié)議的方式,實(shí)現(xiàn)用戶點(diǎn)擊彈出控制器的左邊部分,顯示出右邊部分,并且將對(duì)應(yīng)的頭像和主標(biāo)題,子標(biāo)題顯示到item中
2 定義協(xié)議方法 : (包括可實(shí)現(xiàn)和可不實(shí)現(xiàn))–> 因?yàn)?: 當(dāng)點(diǎn)擊左邊的tableView中的cell的時(shí)候,有右邊有些內(nèi)容是空的,所以如果都定義為必須實(shí)現(xiàn)的,會(huì)出現(xiàn)問(wèn)題
3 定義在XFJLRTableView中的協(xié)議方法第一部分
///MARK : - 定義協(xié)議,用協(xié)議的方法來(lái)控制top中沒(méi)個(gè)按鈕的點(diǎn)擊,彈出控制器設(shè)置相應(yīng)的內(nèi)容@objc protocol XFJTableViewDataSource : NSObjectProtocol { ///左邊的cell顯示的總行數(shù)(需要將左邊的tableView作為參數(shù)傳遞進(jìn)去) func numberOfRowsInLeft (leftTableView : XFJLRTableView) ->Int ///左邊的cell顯示的數(shù)據(jù) func lrTableView(titleDataSource leftRow: Int) ->String? ///左邊的cell顯示的子數(shù)據(jù) func lrTableView(subDataSource leftRow : Int) ->[String] ///左邊的cell顯示的平常圖片(有些是不存在圖片的) optional func lrTableView(normalImageInLeft leftRow : Int) ->String ///左邊的cell顯示的高亮圖片(有些是不存在圖片的) optional func lrTableView(highlightImageLeft leftRow : Int) ->String}
4 設(shè)置代理 :(分類(lèi)模塊代理)
///設(shè)置代理(處理彈出的控制器) weak var delegateSource : XFJTableViewDataSource?
5 注意 : 在對(duì)協(xié)議實(shí)現(xiàn)的部分方法中,已經(jīng)在XFJLRTableView類(lèi)中的數(shù)據(jù)源方法這種實(shí)現(xiàn)了或者是做出了判斷.(上面數(shù)據(jù)源方法中有介紹)
6 對(duì)分類(lèi)用戶點(diǎn)擊后實(shí)現(xiàn)協(xié)議相關(guān)的方法
—-> 6.1 設(shè)置對(duì)應(yīng)的控制器為代理
override func viewDidLoad() { super.viewDidLoad() //快速創(chuàng)建xib let lrTableView = XFJLRTableView.lrTableView() //設(shè)置尺寸 lrTableView.frame = view.bounds //添加tableView view.addSubview(lrTableView) //設(shè)置代理(處理的是彈出控制器的部分) lrTableView.delegateSource = self //設(shè)置代理(處理的是用戶點(diǎn)擊cell的業(yè)務(wù)邏輯) lrTableView.delegate = self }
7 實(shí)現(xiàn)協(xié)議方法
///MARK : - 實(shí)現(xiàn)分類(lèi)的代理方法(處理的是彈出控制器的部分)extension XFJCategoryViewController : XFJTableViewDataSource { ///MARK : - 左側(cè)cell的行數(shù) func numberOfRowsInLeft(leftTableView: XFJLRTableView) -> Int { return categories.count } ///MARK : - 左側(cè)cell的標(biāo)題 func lrTableView(titleDataSource leftRow: Int) -> String? { //取出模型數(shù)據(jù) let categorie = categories[leftRow] return categorie.name } ///MARK : - 左側(cè)cell的子標(biāo)題 func lrTableView(subDataSource leftRow: Int) -> [String] { //取出模型數(shù)據(jù) let categorie = categories[leftRow] //判斷 return categorie.subcategories ?? [] } ///MARK : - cell平常圖片 func lrTableView(normalImageInLeft leftRow: Int) -> String { //取出模型數(shù)據(jù) let categorie = categories[leftRow] return categorie.small_icon! } ///MARK : - cell的高亮圖片 func lrTableView(highlightImageLeft leftRow: Int) -> String { //取出模型數(shù)據(jù) let categorie = categories[leftRow] return categorie.small_highlighted_icon! }}
8 處理用戶點(diǎn)擊item中的某行cell,將cell中顯示的圖片和主標(biāo)題,子標(biāo)題顯示在item中
—-> 8.1 定義協(xié)議 :
///MARK : - 定義協(xié)議,用來(lái)傳遞當(dāng)用戶選擇了彈出的控制器中的某行,將cell中顯示的內(nèi)容顯示到對(duì)應(yīng)的top按鈕中@objc protocol XFJTableViewDelegate : NSObjectProtocol { //點(diǎn)擊了左邊,告訴代理選擇了左邊的哪一行,只要告訴代理不需返回參數(shù) func lrTableView(seletLeftButton leftRow : Int) //點(diǎn)擊了右邊,高度代理點(diǎn)擊了右邊的哪一行,同時(shí)告訴代理選中了左邊的哪一行,不需要返回 func lrTableView(seletRightButton rightRow : Int,seletLeftButton leftRow : Int)}
—-> 8.2 設(shè)置代理 :
///設(shè)置代理(處理選中彈出的控制器中的哪一行) weak var delegate : XFJTableViewDelegate?
—-> 8.3 實(shí)現(xiàn)協(xié)議中的方法
///MARK : - 實(shí)現(xiàn)分類(lèi)的代理方法(處理的是用戶點(diǎn)擊cell的業(yè)務(wù)邏輯)extension XFJCategoryViewController : XFJTableViewDelegate { //用戶點(diǎn)擊了左側(cè),告訴代理點(diǎn)擊了左側(cè)的哪一行 func lrTableView(seletLeftButton leftRow: Int) { //從模型中取出數(shù)據(jù) let catrgoryData = categories[leftRow] //判斷左側(cè)是否有子數(shù)據(jù) let subCatroyData = catrgoryData.subcategories?.count //如果沒(méi)有子數(shù)據(jù),就將數(shù)據(jù)發(fā)送給外界,進(jìn)行數(shù)據(jù)更改 if subCatroyData == 0 { //通過(guò)通知的方式發(fā)送 NSNotificationCenter.defaultCenter().postNotificationName(XFJCategoryNotification, object: nil, userInfo: [XFJCategoryNotificationKey : catrgoryData]) } } //用戶點(diǎn)擊了右側(cè),高度代理點(diǎn)擊了右側(cè)哪一行,同時(shí)告訴代理選中了左側(cè)哪一行 func lrTableView(seletRightButton rightRow: Int, seletLeftButton leftRow: Int) { //從模型中獲取數(shù)據(jù) let catrgoriesData = categories[leftRow] //取出子數(shù)據(jù) let subCatrgoriesData = catrgoriesData.subcategories![rightRow] //發(fā)送通知 NSNotificationCenter.defaultCenter().postNotificationName(XFJCategoryNotification, object: nil, userInfo: [XFJCategoryNotificationKey : catrgoriesData, XFJSubCategoryNotificationKey : subCatrgoriesData]) }}
十三 通知
1 我們是如何將cell中對(duì)應(yīng)的文字和圖片顯示到item中?
—-> 1.1 我們采用發(fā)送通知的方法將相關(guān)數(shù)據(jù)傳遞到item中
2 創(chuàng)建一個(gè)文件用來(lái)保存通知需要的參數(shù)
//分類(lèi)let XFJCategoryNotification = "XFJCategoryNotification"let XFJCategoryNotificationKey = "XFJCategoryNotificationKey"let XFJSubCategoryNotificationKey = "XFJSubCategoryNotificationKey"//地區(qū)let XFJDistrictNotification = "XFJDistrictNotification"let XFJDistrictNotificationKey = "XFJDistrictNotificationKey"let XFJSubDistrictNotificationKey = "XFJSubDistrictNotificationKey"//排序let XFJSortsNotification = "XFJSortsNotification"let XFJSortsNotificationKey = "XFJSortsNotificationKey"
3 發(fā)送通知(分類(lèi)模塊)—-> 通知書(shū)寫(xiě)位置: 協(xié)議方法中
—-> 3.1 代碼塊一 :
//用戶點(diǎn)擊了左側(cè),告訴代理點(diǎn)擊了左側(cè)的哪一行 func lrTableView(seletLeftButton leftRow: Int) { //從模型中取出數(shù)據(jù) let catrgoryData = categories[leftRow] //判斷左側(cè)是否有子數(shù)據(jù) let subCatroyData = catrgoryData.subcategories?.count //如果沒(méi)有子數(shù)據(jù),就將數(shù)據(jù)發(fā)送給外界,進(jìn)行數(shù)據(jù)更改 if subCatroyData == 0 { //通過(guò)通知的方式發(fā)送 NSNotificationCenter.defaultCenter().postNotificationName(XFJCategoryNotification, object: nil, userInfo: [XFJCategoryNotificationKey : catrgoryData]) } }
—-> 3.2 代碼塊二 :
//用戶點(diǎn)擊了右側(cè),高度代理點(diǎn)擊了右側(cè)哪一行,同時(shí)告訴代理選中了左側(cè)哪一行 func lrTableView(seletRightButton rightRow: Int, seletLeftButton leftRow: Int) { //從模型中獲取數(shù)據(jù) let catrgoriesData = categories[leftRow] //取出子數(shù)據(jù) let subCatrgoriesData = catrgoriesData.subcategories![rightRow] //發(fā)送通知 NSNotificationCenter.defaultCenter().postNotificationName(XFJCategoryNotification, object: nil, userInfo: [XFJCategoryNotificationKey : catrgoriesData, XFJSubCategoryNotificationKey : subCatrgoriesData]) }
4 接收通知 : 雖然發(fā)送的通知是匿名通知,但是最好讓能將數(shù)據(jù)提供給誰(shuí)的一方接收通知,這樣也方便設(shè)置相關(guān)數(shù)據(jù)
—-> 4.1 item是屬于XFJHomeViewController類(lèi)的,就讓該類(lèi)來(lái)接收通知,并實(shí)現(xiàn)通知中的方法
—-> 4.2 接收通知代碼 :
//接收分類(lèi)通知 NSNotificationCenter.defaultCenter().addObserver(self, selector: "categoriesNotic:", name: XFJCategoryNotification, object: nil) //接收地區(qū)通知 NSNotificationCenter.defaultCenter().addObserver(self, selector: "districtNotic:", name: XFJDistrictNotification, object: nil) //接收排序通知 NSNotificationCenter.defaultCenter().addObserver(self, selector: "sortsNotic:", name: XFJSortsNotification, object: nil)
—-> 4.3 移除通知 (重要點(diǎn))
//移除通知 deinit { NSNotificationCenter.defaultCenter().removeObserver(self) }
5 實(shí)現(xiàn)接收通知中的方法
—-> 5.2 分類(lèi)
///MARK : - 實(shí)現(xiàn)接收分類(lèi)通知的中調(diào)用的方法extension XFJHomeViewController { @objc private func categoriesNotic(nic : NSNotification) { //取出通知中的內(nèi)容 let catrgoryData = nic.userInfo![XFJCategoryNotificationKey] as! XFJCategories //此處(有可能沒(méi)有子數(shù)據(jù),所以這里不需強(qiáng)轉(zhuǎn)) let subCatroyData = nic.userInfo![XFJSubCategoryNotificationKey] //設(shè)置數(shù)據(jù)(獲取頂部的view) let categoryTopView = topItem?.customView as! XFJTopView //子數(shù)據(jù) let count = catrgoryData.subcategories?.count //判斷 if count == 0 { categoryTopView.title = "美團(tuán)" categoryTopView.subtitle = catrgoryData.name }else{ categoryTopView.title = catrgoryData.name categoryTopView.subtitle = subCatroyData as! String? } //設(shè)置圖標(biāo) categoryTopView.normalName = catrgoryData.icon categoryTopView.heightName = catrgoryData.highlighted_icon //退出poper categoryVC.dismissViewControllerAnimated(true) { () -> Void in //dismiss后允許交互 self.setEnabled() } }}
—-> 5.2 地區(qū)
///MARK : - 實(shí)現(xiàn)接收地區(qū)通知的中調(diào)用的方法extension XFJHomeViewController { @objc private func districtNotic(disNic : NSNotification){ //取出通知中的內(nèi)容 let districtData = disNic.userInfo![XFJDistrictNotificationKey] as! XFJDistrict //此處(有可能沒(méi)有子數(shù)據(jù),所以這里不需強(qiáng)轉(zhuǎn)) let subDistrictData = disNic.userInfo![XFJSubDistrictNotificationKey] //設(shè)置數(shù)據(jù)(獲取頂部的view) let districtTopView = gzItem?.customView as! XFJTopView //子數(shù)據(jù) let count = districtData.subregions?.count //判斷 if count == 0 { districtTopView.title = "美團(tuán)" districtTopView.subtitle = districtData.name }else{ districtTopView.title = districtData.name districtTopView.subtitle = subDistrictData as! String? } //退出poper districtVC.dismissViewControllerAnimated(true) { () -> Void in //dismiss后允許交互 self.setEnabled() } }}
—-> 5.3 排序
///MARK : - 實(shí)現(xiàn)接收排序通知的中調(diào)用的方法extension XFJHomeViewController { @objc private func sortsNotic(sortsNic :NSNotification){ //獲取通知中的內(nèi)容 let sortsData = sortsNic.userInfo![XFJSortsNotificationKey] as! XFJSorts //獲取頂部的view let sortsView = sortItem?.customView as! XFJTopView //設(shè)置數(shù)據(jù) sortsView.subtitle = sortsData.label //移除poper sortsVC.dismissViewControllerAnimated(true) { () -> Void in //dismiss后允許交互 self.setEnabled() } }}
十四 細(xì)節(jié)處理
1 我們發(fā)現(xiàn)當(dāng)運(yùn)行在橫屏的時(shí)候,沒(méi)有問(wèn)題,但是當(dāng)在運(yùn)行的之后轉(zhuǎn)換為豎屏,導(dǎo)航條中item間的距離會(huì)被拉伸,這怎么解決呢?
—-> 1.1 產(chǎn)生這種現(xiàn)象的原因 : autoresizing導(dǎo)致屏幕旋轉(zhuǎn)的時(shí)候,子控件跟隨父控件的拉伸而拉伸
—-> 1.2 解決 :(如下圖)—> 將正方形中間的紅線去除就可以
2 當(dāng)點(diǎn)擊某個(gè)item的時(shí)候,發(fā)現(xiàn)再點(diǎn)擊其他的item的時(shí)候,前一個(gè)item并沒(méi)有退出,這樣給用戶的體驗(yàn)不好.我們通過(guò)代碼來(lái)設(shè)置.
—-> 2.1 在監(jiān)聽(tīng)用戶點(diǎn)擊的按鈕中讓所有的item都取消交互調(diào)用下面代碼
@objc private func setDisabled() { topItem?.enabled = false gzItem?.enabled = false sortItem?.enabled = false }
—-> 2.2 在實(shí)現(xiàn)接收通知中調(diào)用的方法中,在poper被dismiss的時(shí)候,允許用戶交互,調(diào)用下面代碼來(lái)允許交互
@objc private func setEnabled() { topItem?.enabled = true gzItem?.enabled = true sortItem?.enabled = true }
—-> 2.3 在實(shí)現(xiàn)對(duì)item按鈕的監(jiān)聽(tīng)方法中,我們?cè)O(shè)置poper的代理為當(dāng)前控制器(這里只說(shuō)明一段代碼,其它模塊也是一樣的)
//設(shè)置代理 categoryVC.popoverPresentationController?.delegate = self
—-> 2.4 實(shí)現(xiàn)代理方法
///MARK: - 實(shí)現(xiàn)popver代理方法extension XFJHomeViewController : UIPopoverPresentationControllerDelegate { func popoverPresentationControllerDidDismissPopover(popoverPresentationController: UIPopoverPresentationController) { //允許交互 setEnabled() }}
十五 總結(jié)
1 這篇博客我寫(xiě)的可能有點(diǎn)亂,代碼太多,我也沒(méi)辦法具體到某一點(diǎn),只是說(shuō)了大概,介紹了協(xié)議可以實(shí)現(xiàn)這種情況的方法,同時(shí)對(duì)通知的運(yùn)用也是捎帶了,沒(méi)有怎么細(xì)說(shuō).希望你們盡量看吧,看不懂的話,在給我私信吧.能幫到大家的,我一定幫忙.
2 最后還是那句話,大家如果覺(jué)得我寫(xiě)的博客還寫(xiě)的話,麻煩大家多多關(guān)注我的官方博客,謝謝!
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持VEVB武林網(wǎng)。
新聞熱點(diǎn)
疑難解答
圖片精選