纯swift实现ipad版简单美团界面功能

本文实例为大家分享了swift实现ipad版美团界面功能的具体代码,供大家参考,具体内容如下

一 总体功能图一 : (ipad竖屏)

二 总体功能图二 : (ipad横屏)

三 讲解内容

1 搭建美团界面(掌握)

2 ios8.0之后的Popover的运用(重点)

3 协议(掌握)

4 通知(掌握)

5 细节处理

四总体界面

1 由总体的app界面效果,能看出来,一个UIViewController控制器作为UINavigationController的根控制器就能满足条件.

五 导航条设置

1 自定义导航条 : (系统的导航条不能满足需求)

2 创建导航控制器类

3 获取全局的导航条 : (用来作为设置)

//获取导航条
let navigationBar = UINavigationBar.appearanceWhenContainedInInstancesOfClasses([self.classForCoder])

3.1 注意 :一定要用上面的方法来获取,不要用下面的方法来获取,因为通过下面方法获取对导航条的设置,很有可能会造成导航条呈现黑色的情况.

UINavigationBar.appearance()

4 用图片包装导航条

//设置导航条的样式
navigationBar.setBackgroundImage(UIImage(named: "bg_navigationBar_normal"), forBarMetrics: .Default)

5 注意不要忘了将导航控制器的类型改为自定义类型,否则会加载不出来的

六 导航条相关内容处理

1 思路 : 通过观察导航条中的按钮,我们可以看出, 按钮都是由图片;主标题;子标题组成的,所以我们可以通过xib来描述,并且用一个UIView将按钮包裹住,方便修改设置

2 创建继承UIView的类,同时创建同类名的xib

3 xib图

4 xib内部分布结构图

5 如何在xib中分离图片和标题之间的距离? 5.1 下图解答

6 通过给xib拖线,拿到内部属性

//按钮头像
 @IBOutlet weak var iconButton: UIButton!
//头部子标题
 @IBOutlet weak var subtitleLabel: UILabel!
//头部标题
 @IBOutlet weak var title_Label: UILabel!

7 给xib中的属性提供set方法和对应的get方法,方便外边调用修改

//对头部标题提供Set方法
 var title : String? {
  didSet{
   return title_Label.text = title
  }
 }
 //对头部子标题提供set方法
 var subtitle : String? {
  didSet{
   return subtitleLabel.text = subtitle
  }
 }
 //对按钮头像提供set方法(平常的图片)
 var normalName : String? {
  didSet{
   return iconButton.setImage(UIImage(named: normalName!), forState: .Normal)
  }
 }
 //对按钮头像提供set方法(点击后的图片)
 var heightName : String? {
  didSet{
   return iconButton.setImage(UIImage(named: heightName!), forState: .Highlighted)
  }
 }
 //对按钮提供一个get方法
 var getIconButton : UIButton {
  get{
   return iconButton
  }
 }

8 提供一个加载xib的类方法,让外界能通过该方法快速创建xib

//MARK: - 给类扩展一个方法(加载xib)
extension XFJTopView {
 //提供一个快速创建xib的类方法
 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)
  //返回通过xib创建的对象
  return topView
 }
}

9 添加顶部的按钮

—-> 9.1 思路 : 通过添加到由导航条管理的item中的数组中来实现对加载xib的时候按钮的添加

—-> 9.2 导航控制器的根控制器

—-> 9.3 XFJHomeViewController类对导航条中的item的管理(该部分代码比较多,我们通过类扩展来实现)

//MARK: - 设置导航条中的item
extension XFJHomeViewController {
 @objc private func setUpTabBarItem() {
  //设置值item的图片(0)
  let logoItem = UIBarButtonItem(image: UIImage(named: "icon_meituan_logo"), style: .Plain, target: nil, action: nil)
  //对导航条最左边的item赋值
  navigationItem.leftBarButtonItem = logoItem
  //取消导航条左边的item点击
  logoItem.enabled = false

  //设置其他的items(一)
  let item1 = XFJTopView.topView("美团", subTitle: "全部分类", normalImageName: "icon_category_-1", heightImageName: "icon_category_highlighted_-1")
  //设置第一个item
  let topItem = UIBarButtonItem(customView: item1)
  //对按钮的监听
  item1.getIconButton.addTarget(self, action: "presentPopTopViewClick", forControlEvents: .TouchUpInside)
  //赋值
  self.topItem = topItem

  //设置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

  //设置items(三)
  let item3 = XFJTopView.topView("排序", subTitle: "默认排序", normalImageName: "icon_sort", heightImageName: "icon_sort_highlighted")
  let sortItem = UIBarButtonItem(customView: item3)
  item3.getIconButton.addTarget(self, action: "presentPopSortViewClick", forControlEvents: .TouchUpInside)
  //赋值
  self.sortItem = sortItem
  //将item添加到数组中
  navigationItem.leftBarButtonItems = [logoItem,topItem,gzItem,sortItem]

 }
}

七 Popover的弹出

1 分别创建三个类来管理弹出的Popover

2 对顶部三个item所弹出的控制做懒加载创建,保证用到的时候在创建

//MARK: - 懒加载控制器(一)
 private lazy var categoryVC : XFJCategoryViewController = {
  //创建控制器
  let categoryVC = XFJCategoryViewController()
  //设置控制器的样式
  categoryVC.modalPresentationStyle = .Popover
  //返回控制器
  return categoryVC
 }()
 //MARK: - 懒加载控制器(二)
 private lazy var districtVC : XFJDistrictViewController = {
  //创建控制器
  let districtVC = XFJDistrictViewController()
  //设置控制器的样式
  districtVC.modalPresentationStyle = .Popover
  //返回控制器
  return districtVC
 }()
 //MARK: - 懒加载控制器(三)
 private lazy var sortsVC : XFJSortsViewController = {
  //创建控制器
  let sortsVC = XFJSortsViewController()
  //设置控制器的样式
  sortsVC.modalPresentationStyle = .Popover

  //返回控制器
  return sortsVC
 }()

3 根据弹出的Popover类型,我们也可以看出是由两个UITableView组成,并且各占控制器的一半,那么我们这部分也可以通过xib来实现.

—-> 3.1 创建一个类来管理,同时创建xib

3.2 xib内部图

4 弹出Popover(通过在9.3中对item的监听)

—-> 4.1 弹出Popover代码块一 :

//MARK : - 实现监听方法
extension XFJHomeViewController {
 @objc private func presentPopTopViewClick() {
  //弹出位置
  categoryVC.popoverPresentationController?.barButtonItem = topItem
  //设置背景颜色
  categoryVC.popoverPresentationController?.backgroundColor = UIColor.clearColor()
  //model出控制器
  presentViewController(categoryVC, animated: true, completion: nil)
  //取消UIBarButtonItem的交互
  setDisabled()
  //设置代理
  categoryVC.popoverPresentationController?.delegate = self
 }
}

—-> 4.1 弹出Popover代码块二:

extension XFJHomeViewController {
 @objc private func presentPopGzViewClick() {
  //弹出位置
  districtVC.popoverPresentationController?.barButtonItem = gzItem
  //设置背景颜色
  districtVC.popoverPresentationController?.backgroundColor = UIColor.clearColor()
  //
  //model出控制器
  presentViewController(districtVC, animated: true, completion: nil)
  //取消UIBarButtonItem的交互
  setDisabled()
  //设置代理
  districtVC.popoverPresentationController?.delegate = self
 }
}

—-> 4.1 弹出Popover代码块三 :

extension XFJHomeViewController {
 @objc private func presentPopSortViewClick() {
  //弹出控制器的位置
  sortsVC.popoverPresentationController?.barButtonItem = sortItem
  //设置背景颜色
  sortsVC.popoverPresentationController?.backgroundColor = UIColor.whiteColor()
  //model出控制器
  presentViewController(sortsVC, animated: true, completion: nil)
  //取消UIBarButtonItem的交互
  setDisabled()
  //设置代理
  sortsVC.popoverPresentationController?.delegate = self
 }
}

八 处理弹出的Popover相关数据(全部由对应的模型来决定)

1 获取xib中的对象并且提供一个快速创建xib的类方法

//左边的tableView
 @IBOutlet weak var leftTableView: UITableView!
 //右边的tableView
 @IBOutlet weak var rightTableView: UITableView!
 //模型分类数据
 var categories : [XFJCategories]?
 //地区模块的数据
 var DistrictData : [XFJDistrict]?
 //定义一个属性,用来记录用户点击了左侧的哪一行
 var seletIndex : Int?

 //快速创建xib的类方法
 class func lrTableView() ->XFJLRTableView {
  return NSBundle.mainBundle().loadNibNamed("XFJLRTableView", owner: nil, options: nil).last as! XFJLRTableView
 }
 //分类的子数据
 private var subData : [String]?

2 通过在xib中设置代理和数据源实现有关数据源方法

—-> 2.1 数据源方法一 : cell的个数

//MARK: - 数据源方法
extension XFJLRTableView : UITableViewDataSource {
 //cell的个数
 func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
  //判断是左边还是右边
  if tableView == leftTableView { //左边
   return (delegateSource?.numberOfRowsInLeft(self))!
  }else{ //右边
   return subData?.count ?? 0
  }
 }

—-> 2.2 数据源方法二 : cell的内容

 //cell的内容
 func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
  //创建cell
  var cell = UITableViewCell?()
  //判断
  if tableView == leftTableView {
   //创建自定义cell
   cell = XFJLeftViewCell.leftViewCell(tableView)
   //设置文字
   cell?.textLabel?.text = delegateSource?.lrTableView(titleDataSource: indexPath.row)
   //设置头像(平常图)--注意 :lrTableViewWithNormalImageInLeft千万要注意大小写
   if delegate?.respondsToSelector("lrTableViewWithNormalImageInLeft:") == true {
    cell?.imageView?.image = UIImage(named: (delegateSource?.lrTableView!(normalImageInLeft: indexPath.row))!)
   }

   //设置头像(高亮图)--注意 :lrTableViewWithHighlightImageLeft千万要注意大小写
   if delegate?.respondsToSelector("lrTableViewWithHighlightImageLeft:") == true {
    cell?.imageView?.highlightedImage = UIImage(named: (delegateSource?.lrTableView!(highlightImageLeft: indexPath.row))!)
   }

  }else{
   cell = XFJRightViewCell.righViewCell(tableView)
   //设置内容
   cell?.textLabel?.text = subData![indexPath.row]
  }
  return cell!
 }

—-> 2.3 数据源方法三 : 点击cell做出的相应数据改变

//MARK: - 点击左边的cell
extension XFJLRTableView : UITableViewDelegate {
 func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
  //判断是否是左边
  if tableView == leftTableView {//左边
   //获取子数据
   subData = delegateSource?.lrTableView(subDataSource: indexPath.row)
   //调用协议方法(传入用户点击的哪行)
   delegate?.lrTableView(seletLeftButton: indexPath.row)
   //记录用户点击了左侧的哪行
   seletIndex = indexPath.row
   //刷新表格
   rightTableView.reloadData()
  }else{ //右边
   //调用协议方法,传入右侧点击了哪行和左侧选中了哪行
   delegate?.lrTableView(seletRightButton: indexPath.row, seletLeftButton: seletIndex!)
  }
 }
}

九 创建模型

1 导入plist文件

2 创建继承NSObject的类,用来设置需要用到的模型属性

-> 2.1 模型属性一 :(分类中所需要的模型属性)

 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 在各自管理的类中懒加载模型(采用MJ框架加载模型)

—-> 3.1 分类模块中懒加载模型

//懒加载模型
 private lazy var categories : [XFJCategories] = {
  let categoriesData = XFJCategories.objectArrayWithFilename("categories.plist") as NSArray
  //返回模型
  return categoriesData as! [XFJCategories]
 }()

—-> 3.2 地区模块中懒加载模型

 //懒加载
 private lazy var DistrictView :[XFJDistrict] = {
  let DistrictData = XFJDistrict.objectArrayWithFilename("gz.plist") as NSArray
  //返回模型数据
  return DistrictData as! [XFJDistrict]
 }()

—-> 3.3 排序模块中懒加载模型

//创建一个属性记录按钮的点击状态
 var previousButton = UIButton()
 //懒加载
 private lazy var sortsData : [XFJSorts] = {
  //模型转化
  let sortsDatas = XFJSorts.objectArrayWithFilename("sorts.plist") as NSArray
  //返回模型
  return sortsDatas as! [XFJSorts]
 }()

十 自定义cell

1 通过功能图知道Popover出来的控制器中cell中既展示图片又展示文字,所以我们通过自定义cell来设置 2 自定义左边的tableViewCell

class XFJLeftViewCell: UITableViewCell {
  //左边的tableView
  class func leftViewCell(tableView : UITableView) ->XFJLeftViewCell {
    //绑定cell类型
    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)
    //设置背景图片
    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 该方法是在数据源方法中调用的,用来加载cell

3 自定义右边的tableViewCell

class XFJRightViewCell: UITableViewCell {
  //右边的tableView
  class func righViewCell(tableView : UITableView) ->XFJRightViewCell {
    //定义cell的标识
    let rightCell = "rightCell"
    //创建cell
    var cell = tableView.dequeueReusableCellWithIdentifier(rightCell)
    //判断
    if cell == nil {
      cell = XFJRightViewCell(style: .Default, reuseIdentifier: rightCell)
    }
    //返回cell
    return cell as! XFJRightViewCell
  }

  //设置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")
  }
}

十一 上半部分总结

1 用上面这些方法确实可以达到用户点击item,弹出对应的控制器.但是上面的代码只是写了对其中一个点击item弹出的业逻辑,还有中间的item并没与处理,如果采用这样的方法处理,那么代码量太多了,并且看起来也显得没什么技术含量,我们最终将不会采用这种方法实现.

十二 代理 协议(最终实现的方案)

1 需要实现的功能 : 通过代理协议的方式,实现用户点击弹出控制器的左边部分,显示出右边部分,并且将对应的头像和主标题,子标题显示到item中

2 定义协议方法 : (包括可实现和可不实现)–> 因为 : 当点击左边的tableView中的cell的时候,有右边有些内容是空的,所以如果都定义为必须实现的,会出现问题

3 定义在XFJLRTableView中的协议方法第一部分

///MARK : - 定义协议,用协议的方法来控制top中没个按钮的点击,弹出控制器设置相应的内容
@objc protocol XFJTableViewDataSource : NSObjectProtocol {
  ///左边的cell显示的总行数(需要将左边的tableView作为参数传递进去)
  func numberOfRowsInLeft (leftTableView : XFJLRTableView) ->Int
  ///左边的cell显示的数据
  func lrTableView(titleDataSource leftRow: Int) ->String?
  ///左边的cell显示的子数据
  func lrTableView(subDataSource leftRow : Int) ->[String]
  ///左边的cell显示的平常图片(有些是不存在图片的)
  optional func lrTableView(normalImageInLeft leftRow : Int) ->String
  ///左边的cell显示的高亮图片(有些是不存在图片的)
  optional func lrTableView(highlightImageLeft leftRow : Int) ->String
}

4 设置代理 :(分类模块代理)

///设置代理(处理弹出的控制器)
  weak var delegateSource : XFJTableViewDataSource?

5 注意 : 在对协议实现的部分方法中,已经在XFJLRTableView类中的数据源方法这种实现了或者是做出了判断.(上面数据源方法中有介绍)

6 对分类用户点击后实现协议相关的方法

—-> 6.1 设置对应的控制器为代理

override func viewDidLoad() {
    super.viewDidLoad()
    //快速创建xib
    let lrTableView = XFJLRTableView.lrTableView()
    //设置尺寸
    lrTableView.frame = view.bounds
    //添加tableView
    view.addSubview(lrTableView)
    //设置代理(处理的是弹出控制器的部分)
    lrTableView.delegateSource = self
    //设置代理(处理的是用户点击cell的业务逻辑)
    lrTableView.delegate = self
  }

7 实现协议方法

///MARK : - 实现分类的代理方法(处理的是弹出控制器的部分)
extension XFJCategoryViewController : XFJTableViewDataSource {
  ///MARK : - 左侧cell的行数
  func numberOfRowsInLeft(leftTableView: XFJLRTableView) -> Int {
    return categories.count
  }
  ///MARK : - 左侧cell的标题
  func lrTableView(titleDataSource leftRow: Int) -> String? {
    //取出模型数据
    let categorie = categories[leftRow]
    return categorie.name
  }
  ///MARK : - 左侧cell的子标题
  func lrTableView(subDataSource leftRow: Int) -> [String] {
    //取出模型数据
    let categorie = categories[leftRow]
    //判断
    return categorie.subcategories ?? []
  }
  ///MARK : - cell平常图片
  func lrTableView(normalImageInLeft leftRow: Int) -> String {
    //取出模型数据
    let categorie = categories[leftRow]
    return categorie.small_icon!
  }
  ///MARK : - cell的高亮图片
  func lrTableView(highlightImageLeft leftRow: Int) -> String {
    //取出模型数据
    let categorie = categories[leftRow]
    return categorie.small_highlighted_icon!
  }
}

8 处理用户点击item中的某行cell,将cell中显示的图片和主标题,子标题显示在item中

—-> 8.1 定义协议 :

///MARK : - 定义协议,用来传递当用户选择了弹出的控制器中的某行,将cell中显示的内容显示到对应的top按钮中
@objc protocol XFJTableViewDelegate : NSObjectProtocol {
  //点击了左边,告诉代理选择了左边的哪一行,只要告诉代理不需返回参数
  func lrTableView(seletLeftButton leftRow : Int)
  //点击了右边,高度代理点击了右边的哪一行,同时告诉代理选中了左边的哪一行,不需要返回
  func lrTableView(seletRightButton rightRow : Int,seletLeftButton leftRow : Int)
}

—-> 8.2 设置代理 :

///设置代理(处理选中弹出的控制器中的哪一行)
  weak var delegate : XFJTableViewDelegate?

—-> 8.3 实现协议中的方法

///MARK : - 实现分类的代理方法(处理的是用户点击cell的业务逻辑)
extension XFJCategoryViewController : XFJTableViewDelegate {
  //用户点击了左侧,告诉代理点击了左侧的哪一行
  func lrTableView(seletLeftButton leftRow: Int) {
    //从模型中取出数据
    let catrgoryData = categories[leftRow]
    //判断左侧是否有子数据
    let subCatroyData = catrgoryData.subcategories?.count
    //如果没有子数据,就将数据发送给外界,进行数据更改
    if subCatroyData == 0 {
      //通过通知的方式发送
      NSNotificationCenter.defaultCenter().postNotificationName(XFJCategoryNotification, object: nil, userInfo: [XFJCategoryNotificationKey : catrgoryData])
    }

  }
  //用户点击了右侧,高度代理点击了右侧哪一行,同时告诉代理选中了左侧哪一行
  func lrTableView(seletRightButton rightRow: Int, seletLeftButton leftRow: Int) {
    //从模型中获取数据
    let catrgoriesData = categories[leftRow]
    //取出子数据
    let subCatrgoriesData = catrgoriesData.subcategories![rightRow]
    //发送通知
    NSNotificationCenter.defaultCenter().postNotificationName(XFJCategoryNotification, object: nil, userInfo: [XFJCategoryNotificationKey : catrgoriesData, XFJSubCategoryNotificationKey : subCatrgoriesData])
  }
}

十三 通知

1 我们是如何将cell中对应的文字和图片显示到item中?

—-> 1.1 我们采用发送通知的方法将相关数据传递到item中

2 创建一个文件用来保存通知需要的参数

//分类
let XFJCategoryNotification = "XFJCategoryNotification"
let XFJCategoryNotificationKey = "XFJCategoryNotificationKey"
let XFJSubCategoryNotificationKey = "XFJSubCategoryNotificationKey"

//地区
let XFJDistrictNotification = "XFJDistrictNotification"
let XFJDistrictNotificationKey = "XFJDistrictNotificationKey"
let XFJSubDistrictNotificationKey = "XFJSubDistrictNotificationKey"

//排序
let XFJSortsNotification = "XFJSortsNotification"
let XFJSortsNotificationKey = "XFJSortsNotificationKey"

3 发送通知(分类模块)—-> 通知书写位置: 协议方法中

—-> 3.1 代码块一 :

//用户点击了左侧,告诉代理点击了左侧的哪一行
  func lrTableView(seletLeftButton leftRow: Int) {
    //从模型中取出数据
    let catrgoryData = categories[leftRow]
    //判断左侧是否有子数据
    let subCatroyData = catrgoryData.subcategories?.count
    //如果没有子数据,就将数据发送给外界,进行数据更改
    if subCatroyData == 0 {
      //通过通知的方式发送
      NSNotificationCenter.defaultCenter().postNotificationName(XFJCategoryNotification, object: nil, userInfo: [XFJCategoryNotificationKey : catrgoryData])
    }

  }

—-> 3.2 代码块二 :

//用户点击了右侧,高度代理点击了右侧哪一行,同时告诉代理选中了左侧哪一行
  func lrTableView(seletRightButton rightRow: Int, seletLeftButton leftRow: Int) {
    //从模型中获取数据
    let catrgoriesData = categories[leftRow]
    //取出子数据
    let subCatrgoriesData = catrgoriesData.subcategories![rightRow]
    //发送通知
    NSNotificationCenter.defaultCenter().postNotificationName(XFJCategoryNotification, object: nil, userInfo: [XFJCategoryNotificationKey : catrgoriesData, XFJSubCategoryNotificationKey : subCatrgoriesData])
  }

4 接收通知 : 虽然发送的通知是匿名通知,但是最好让能将数据提供给谁的一方接收通知,这样也方便设置相关数据

—-> 4.1 item是属于XFJHomeViewController类的,就让该类来接收通知,并实现通知中的方法

—-> 4.2 接收通知代码 :

//接收分类通知
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "categoriesNotic:", name: XFJCategoryNotification, object: nil)
    //接收地区通知
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "districtNotic:", name: XFJDistrictNotification, object: nil)
    //接收排序通知
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "sortsNotic:", name: XFJSortsNotification, object: nil)

—-> 4.3 移除通知 (重要点)

//移除通知
  deinit {
    NSNotificationCenter.defaultCenter().removeObserver(self)
  }

5 实现接收通知中的方法

—-> 5.2 分类

///MARK : - 实现接收分类通知的中调用的方法
extension XFJHomeViewController {
    @objc private func categoriesNotic(nic : NSNotification) {
    //取出通知中的内容
    let catrgoryData = nic.userInfo![XFJCategoryNotificationKey] as! XFJCategories
    //此处(有可能没有子数据,所以这里不需强转)
    let subCatroyData = nic.userInfo![XFJSubCategoryNotificationKey]
    //设置数据(获取顶部的view)
    let categoryTopView = topItem?.customView as! XFJTopView
    //子数据
    let count = catrgoryData.subcategories?.count
    //判断
    if count == 0 {
      categoryTopView.title = "美团"
      categoryTopView.subtitle = catrgoryData.name
    }else{
      categoryTopView.title = catrgoryData.name
      categoryTopView.subtitle = subCatroyData as! String?
    }
    //设置图标
    categoryTopView.normalName = catrgoryData.icon
    categoryTopView.heightName = catrgoryData.highlighted_icon

    //退出poper
     categoryVC.dismissViewControllerAnimated(true) { () -> Void in
      //dismiss后允许交互
      self.setEnabled()
    }
  }
}

—-> 5.2 地区

///MARK : - 实现接收地区通知的中调用的方法
extension XFJHomeViewController {
  @objc private func districtNotic(disNic : NSNotification){
  //取出通知中的内容
  let districtData = disNic.userInfo![XFJDistrictNotificationKey] as! XFJDistrict
  //此处(有可能没有子数据,所以这里不需强转)
  let subDistrictData = disNic.userInfo![XFJSubDistrictNotificationKey]
  //设置数据(获取顶部的view)
  let districtTopView = gzItem?.customView as! XFJTopView
  //子数据
  let count = districtData.subregions?.count
  //判断
  if count == 0 {
    districtTopView.title = "美团"
    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 : - 实现接收排序通知的中调用的方法
extension XFJHomeViewController {
  @objc private func sortsNotic(sortsNic :NSNotification){
    //获取通知中的内容
    let sortsData = sortsNic.userInfo![XFJSortsNotificationKey] as! XFJSorts
    //获取顶部的view
    let sortsView = sortItem?.customView as! XFJTopView
    //设置数据
    sortsView.subtitle = sortsData.label

    //移除poper
    sortsVC.dismissViewControllerAnimated(true) { () -> Void in
      //dismiss后允许交互
      self.setEnabled()
    }
  }
}

十四 细节处理

1 我们发现当运行在横屏的时候,没有问题,但是当在运行的之后转换为竖屏,导航条中item间的距离会被拉伸,这怎么解决呢?

—-> 1.1 产生这种现象的原因 : autoresizing导致屏幕旋转的时候,子控件跟随父控件的拉伸而拉伸

—-> 1.2 解决 :(如下图)—> 将正方形中间的红线去除就可以

2 当点击某个item的时候,发现再点击其他的item的时候,前一个item并没有退出,这样给用户的体验不好.我们通过代码来设置.

—-> 2.1 在监听用户点击的按钮中让所有的item都取消交互调用下面代码

@objc private func setDisabled() {
    topItem?.enabled = false
    gzItem?.enabled = false
    sortItem?.enabled = false
  }

—-> 2.2 在实现接收通知中调用的方法中,在poper被dismiss的时候,允许用户交互,调用下面代码来允许交互

@objc private func setEnabled() {
    topItem?.enabled = true
    gzItem?.enabled = true
    sortItem?.enabled = true
  }

—-> 2.3 在实现对item按钮的监听方法中,我们设置poper的代理为当前控制器(这里只说明一段代码,其它模块也是一样的)

 //设置代理
    categoryVC.popoverPresentationController?.delegate = self

—-> 2.4 实现代理方法

///MARK: - 实现popver代理方法
extension XFJHomeViewController : UIPopoverPresentationControllerDelegate {
  func popoverPresentationControllerDidDismissPopover(popoverPresentationController: UIPopoverPresentationController) {
    //允许交互
    setEnabled()
  }
}

十五 总结

1 这篇博客我写的可能有点乱,代码太多,我也没办法具体到某一点,只是说了大概,介绍了协议可以实现这种情况的方法,同时对通知的运用也是捎带了,没有怎么细说.希望你们尽量看吧,看不懂的话,在给我私信吧.能帮到大家的,我一定帮忙.

2 最后还是那句话,大家如果觉得我写的博客还写的话,麻烦大家多多关注我的官方博客,谢谢!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Swift 3.1聊天界面键盘效果的实现详解

    前言 最近写的 Swift 项目里要实现一个聊天界面,在处理键盘弹出的时候遇到了一点麻烦. 麻烦就在于键盘弹出后如何处理屏幕和键盘的关系 经过一番死磕,终于做出了想要的效果,效果如下: 注:原本项目是 Swift 2.3 写的,为了写这篇博客,用 Swift 3.1 重新实现了一遍. 感受:方法名真的缩短了不少,

  • 纯swift实现ipad版简单美团界面功能

    本文实例为大家分享了swift实现ipad版美团界面功能的具体代码,供大家参考,具体内容如下 一 总体功能图一 : (ipad竖屏) 二 总体功能图二 : (ipad横屏) 三 讲解内容 1 搭建美团界面(掌握) 2 ios8.0之后的Popover的运用(重点) 3 协议(掌握) 4 通知(掌握) 5 细节处理 四总体界面 1 由总体的app界面效果,能看出来,一个UIViewController控制器作为UINavigationController的根控制器就能满足条件. 五 导航条设置 1

  • 使用Qt QSS绘制简单美化界面功能

    目录 使用Qt绘制一个简约美观的界面-使用QSS简单美化 基本控件布局 界面的简单美化 QSS 添加图片 方法1:添加资源 方法2:直接指定图片在计算机中的绝对 / 相对路径 使用Qt绘制一个简约美观的界面-使用QSS简单美化 基本控件布局 以绘制登录界面为例,创建一个继承自Qwidget的设计师界面类 为了使得控件排放整齐有序,可以使用layout布局进行辅助 首先,添加控件,然后按照类似css的页面布局方式,在控件下方添加一Vertical Spacer垫片,用于控制该控件与其他控件的下边距

  • Swift 中闭包的简单使用

    本文主要是介绍Swift中闭包的简单使用,将从"闭包的定义"."闭包的创建.赋值.调用"."闭包常见的几种使用场景","使用闭包可能引起的循环强引用" 四个方面入手,重点介绍闭包如何使用,没有高深的概念,只是专注于实际使用,属于入门级水平,后面还会有关于闭包更加详细和深入理解的文章.希望大家在阅读完本文后能够对闭包有一个整体的理解以及能够简单的使用它. 闭包的定义 在Swift开发文档中是这样介绍闭包的:闭包是可以在你的代码中

  • 自己动手写一个java版简单云相册

    动手写一个java版简单云相册,实现的功能是: 用户可以一次上传一个至多个文件. 用户可以下载其他人上传的图片. 用户可以查看其他所有人的图片. 用户只能删除通过自己IP上传的图片. 用到的技术: 文件上传下载.设计模式.Dom4j.xPath等. 先看下2个页面: 源代码: web.xml: <?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" xmlns=

  • JSP制作简单登录界面实例

    现在很多web项目都能用到登录界面,本文介绍一下JSP制作简单登录界面,分享给大家,具体如下: 运行环境 eclipse+tomcat+MySQL 不知道的可以参考Jsp运行环境--Tomcat 项目列表 这里我先把jsp文件先放在Web-INF外面访问 1.需要建立的几个文件在图上.jsp 2.还要导入MySQL的jar包mysql-5.0.5.jar,导到WEB-INF中的lib文件夹就可以不需要Bulid Path 3.开始编写代码: 代码演示: index.jsp就好像一般网站的首页一样

  • Python Tkinter 简单登录界面的实现

    如下所示: from tkinter import * class Reg (Frame): def __init__(self,master): frame = Frame(master) frame.pack() self.lab1 = Label(frame,text = "账户:") self.lab1.grid(row = 0,column = 0,sticky = W) self.ent1 = Entry(frame) self.ent1.grid(row = 0,colu

  • 使用Python中tkinter库简单gui界面制作及打包成exe的操作方法(二)

    上一篇我们写了怎么将xmind转换成想要的excel格式,这篇再讲一下用Python自带的tkinter库设计一个简单的gui界面,让我们的xmind路径,用例版本执行等都通过这个gui界面来输入,生成我们需要的excel文件. Python要生成gui,库还是比较多的比如wxpython,这个我看了下,感觉比较难懂,毕竟只是设计一个比较简单的gui界面,所以就使用了tkinter库,感觉这个还是比较方便易懂的,大家可以在这里学习tkinter库http://c.biancheng.net/py

  • 用Python给图像算法做个简单应用界面

    以前在Windows上做界面用MFC,现在做算法都是基于Python,所以转用Python的Tkinter库来做.主要是能使用Opencv和Torch处理数据,然后在界面上显示. 效果如下: 主要包括3个板块,其余还有一些小功能: 1.显示固定的图片.或从电脑加载一张图片并显示(涉及到按钮的响应函数编写和弹窗) 2.下拉框和文本框的使用 3.进度条的使用(涉及到多线程) Tkinter支持控件自动调整布局,但是时间比较赶就不研究了,使用固定位置布局,界面也不给调整. 控件名称 Buttom 按钮

  • java实现简单登录界面的实战过程

    目录 一.概要 二.分类部分 三.代码实现 总结 一.概要 我们可以用java实现简单的登录界面. 如上效果,直观但也需要一步一步来完成,从界面弹窗的设置,图片的插入,文本框的设置,到登录的按钮,全由代码来实现. 二.分类部分 LoginUI类:实现界面的设置,构建方法,封装好所有的界面开发代码 ①initUI方法 :1.创建窗体对象: 2.设置窗体的相关属性(标题.尺寸.大小.关闭.可视化): 3.创建组件对象,按钮,输入框: 4.界面窗口添加按钮: 5.按钮添加监听器. ②main方法 :用

  • Vue实现简单登录界面

    本文实例为大家分享了Vue实现简单登录界面的具体代码,供大家参考,具体内容如下 实现: 界面实现 表单规则校验 结合后台 api 校验 提示消息 App.vue <template>   <div id="app"> <!--路由占位符 -->    <router-view></router-view>   </div> </template> <script> export defaul

随机推荐