swift-MJRefresh下拉刷新,上拉加载(分页)

//
//  BannerViewController.swift
//  iosTest
//
//

import UIKit
import SwiftyJSON
import Alamofire
import MJRefresh

//实现SliderGalleryControllerDelegate接口
class BannerViewController: UIViewController,SliderGalleryControllerDelegate,UITableViewDelegate,UITableViewDataSource {
    //顶部下拉刷新
    //let top_header = MJRefreshNormalHeader()//这个是原声的样式,不能自定一图片轮播
    let top_header_style = MJRefreshGifHeader()//这个可以设置下拉刷新的图片动画效果
    //底部上拉加载
    let bottom_footer = MJRefreshAutoNormalFooter()
    //TableView列表控件
    @IBOutlet var my_tableview: UITableView!
    //获取屏幕的宽度
    let screenWidth = UIScreen.main.bounds.size.width
    //获取屏幕的高度
    let screenHeight = UIScreen.main.bounds.size.height
    //自定义的图片轮播的组件
    var sliderGallery : SliderGalleryController!
    //图片轮播的数据源(String类型的数组)
    var imgageData = [String]()
    //tableViewData列表数据源(JSON数组)
    var tableViewData = Array<JSON>()

    override func viewDidLoad() {
        super.viewDidLoad()
        //请求服务获取轮播图片
        getImageData()
        getTableViewData("up")
        initMJRefresh()

    }
    //图片轮播组件接口获取数据源的方法
    func galleryDataSource() -> [String] {
        return imgageData
    }
    //图片轮播组件接口的方法,获取内部scrollView的尺寸
    func galleryScrollerViewSize() -> CGSize {
        return CGSize(width: screenWidth-20, height: (screenWidth-20)/4*3)
    }
    //点击事件响应
    @objc func handleTapAction(_ tap:UITapGestureRecognizer) -> Void {
        //获取图片的索引值
        let index = sliderGallery.currentIndex
        print("宝宝你点击了\(index)张图片")
    }

    //tableView的分区(分区是啥可以看这篇文章 https://blog.csdn.net/lwjok2007/article/details/49246613)
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    //TableView需要展示的行数
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.tableViewData.count
    }
    //设置每行的单元格的高度
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 100
    }
    //设置每一行的内容
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        // 这里 withIdentifier 的参数就是在做 tableview初始化时创建的单元格设置的 forCellReuseIdentifier 值
        let cell:MyTableViewCell = my_tableview.dequeueReusableCell(withIdentifier: "myCell") as! MyTableViewCell
        //设置cell的值
        cell.text_money.text = self.tableViewData[indexPath.row]["***"].stringValue
        cell.text3.text = self.tableViewData[indexPath.row]["***"].stringValue
        cell.text2.text = self.tableViewData[indexPath.row]["***"].stringValue
        cell.text1.text = self.tableViewData[indexPath.row]["***"].stringValue
        return cell
    }

    //顶部下拉刷新时执行的函数
    @objc func headerRefresh(){
        print("下拉刷新了")
        //服务器请求数据的函数
        self.getTableViewData()
        //重新加载tableView数据
        //self.my_tableview.reloadData()
        //结束下拉刷新
        self.my_tableview.mj_header.endRefreshing()
    }

    //上拉加载执行的函数
    @objc func buttomFooterLoad(){
        print("上拉加载")
        //服务器请求数据的函数
        self.getTableViewData()
        //结束刷新
        self.my_tableview.mj_footer.endRefreshing()
    }

    //初始化下拉刷新/上拉加载
    func initMJRefresh(){
       //下拉刷新相关设置
        top_header_style.setRefreshingTarget(self, refreshingAction: #selector(BannerViewController.headerRefresh))
        // Set the ordinary state of animated images
        var idleImages = [UIImage]()
        //添加动画图片
        for i in 1...3 {
            idleImages.append(UIImage(named:"b\(i)")!)
        }
        top_header_style.setImages(idleImages, for: .idle)

        top_header_style.setImages(idleImages, for: .pulling)

        top_header_style.setImages(idleImages, for: .refreshing)

        //将下拉刷新控件与 tableView控件绑定起来
        self.my_tableview.mj_header = top_header_style
        //初始化上拉加载
        init_bottomFooter()
    }

    //上拉加载初始化设置
    func init_bottomFooter(){
        //上刷新相关设置
        bottom_footer.setRefreshingTarget(self, refreshingAction: #selector(BannerViewController.buttomFooterLoad))
        //self.bottom_footer.stateLabel.isHidden = true // 隐藏文字
        //是否自动加载(默认为true,即表格滑到底部就自动加载,这个我建议关掉,要不然效果会不好)
        bottom_footer.isAutomaticallyRefresh = false
        bottom_footer.isAutomaticallyChangeAlpha = true //自动更改透明度
        //修改文字
        bottom_footer.setTitle("上拉上拉上拉", for: .idle)//普通闲置的状态
        bottom_footer.setTitle("加载加载加载", for: .refreshing)//正在刷新的状态
        bottom_footer.setTitle("没有没有更多数据了", for: .noMoreData)//数据加载完毕的状态
        //将上拉加载的控件与 tableView控件绑定起来
        self.my_tableview.mj_footer = bottom_footer
    }

    //数据请求成功后初始化TableView
    func initTableView(){
        //加载数据
        self.my_tableview.reloadData()
        //设置tableView控件的位置
        self.my_tableview.frame = CGRect(x: 10, y: 200, width: screenWidth, height: screenHeight - 160)
        //设置delegate的事件监听
        self.my_tableview.delegate = self
        //设置dataSource的事件监听
        self.my_tableview.dataSource = self
        //去除单元格分割线
        self.my_tableview.separatorStyle = .none
        //创建一个重用的单元格(第一个参数为创建单元格的样式文件的名字,这里就是MyTableViewCell.xib文件,最好把它的'Restoration ID'也设置为跟文件名一样的;第二个参数为创建单元格的标识名)
        self.my_tableview.register(UINib(nibName: "MyTableViewCell", bundle: nil), forCellReuseIdentifier: "myCell")

    }

    //初始化轮播组件
    func initSliderGallery(){
        //初始化图片轮播组件
        sliderGallery = SliderGalleryController()
        //设置 SliderGalleryControllerDelegate 接口的监听事件
        sliderGallery.delegate = self
        //设置轮播组件的位置(这里 height设置170,SliderGalleryController同时也要设置成170)
        sliderGallery.view.frame = CGRect(x: 10, y: 30, width: screenWidth-20, height: 170)
        //将图片轮播组件添加到当前视图
        self.addChildViewController(sliderGallery)
        self.view.addSubview(sliderGallery.view)

        //添加组件的点击事件
        let tap = UITapGestureRecognizer(target: self, action: #selector(BannerViewController.handleTapAction(_:)))
        sliderGallery.view.addGestureRecognizer(tap)
    }
    //请求服务器获取轮播图片的数据
    func getImageData(){
      //获取当前时间
      let now = Date()
      //当前时间的时间戳
      let timeInterval:TimeInterval = now.timeIntervalSince1970
      let timeStamp = String(timeInterval)
      let url = URL(string: "http://47.92.107.28:8000/****/****.f?_=\(timeStamp)")!
        Alamofire.request(url,method: .get,parameters: nil,encoding: URLEncoding.default,headers:nil).responseJSON { response
            in
            switch response.result.isSuccess {
            case true:
                if let value = response.result.value{
                    self.imgageData = []
                    //获取返回的值,转为json对象
                    let img_json = JSON(value)
                    //json转字符串
                    let json_str = img_json.rawString()
                    let zhu_url = "http://47.92.107.28:8000"
                    //遍历json数据
                    for(key,item) in img_json["imgs"] {
                        //print("src的值:\(item["src"])")
                        //如果取得的 src 的值为 String类型的话就添加到数组中
                        if let img_url = item["src"].string{
                            //将图片路径添加到数组中
                            self.imgageData.append(zhu_url+img_url)
                        }
                    }
                    let str = self.imgageData.joined()
                    //print("请求到返回的数据\(json_str)")
                    //初始化轮播组件
                    self.initSliderGallery()
                }
            case false:
                print(response.result.error)
                UIAlertController.showAlert(message: "网络连接失败")
            }
        }
    }
    var firset_order:String? = nil//下拉刷新时第一条数据的标识(当前记录的是时间)
    var last_order:String? = nil //上拉刷新时最后一条数据的标识(当前记录的是时间)
    //获取tableview的数据源(第二步)
    func getTableViewData(_ upordown:String) -> Void {
        var parameters_json = Dictionary<String,String>()
        parameters_json["a"] = upordown //用于标识时上拉还是下拉
        parameters_json["l"] = "10" //返回的数据个数

        //下拉
        if upordown == "up"{
            if firset_order != nil {
                parameters_json["b"] = firset_order
            }else{
                parameters_json["b"] = nil
            }
        }
        //上拉
        if upordown == "down"{
            if last_order != nil {
                parameters_json["b"] = last_order
            }else{
                parameters_json["b"] = nil
            }
        }
        Alamofire.request("http://*****",method: .post,parameters:parameters_json).responseJSON{(response) in
            switch response.result.isSuccess{
            case true:
                if let value = response.result.value{
                    //将返回的值转为json对象
                    let data_json = JSON(value)

                    //获取的新的数据,将其转为json数组
                    var tmp_order = data_json["*****"].arrayValue
                    // let json_str = data_json["*****"].rawString()
                    print("获取首页数据:\(tmp_order.count)")
                    let len = tmp_order.count


                    if upordown == "down"{
                        //重置上拉加载
                        self.my_tableview.mj_footer.resetNoMoreData()
                    }

                    if len > 0 {
                        //下拉
                        if upordown == "up"{                    
                            if self.last_order == nil {
                                //下拉的时候,当记录最后一条数据的标识为空时,为它赋值
                                self.last_order = tmp_order[len - 1]["***"].stringValue 
                            }
                            //记录每次最新数据第一条数据的时间(因为下拉要的永远是最新数据的第一条)
                            self.firset_order = tmp_order[0]["***"].stringValue
                        }
                        //上拉
                        if upordown == "down"{
                            if self.firset_order == nil {
                                //下拉的时候,当记录第一条数据的标识为空时,为它赋值
                                self.firset_order = tmp_order[0]["***"].stringValue
                            }
                            //记录每次最新数据最后一条数据的时间(因为上拉要的永远是最新数据的最后一条)
                            self.last_order = tmp_order[len - 1]["***"].stringValue
                        }
                    }else{
                        //如果为上拉的话
                        if upordown == "down"{
                            self.my_tableview.mj_footer.endRefreshingWithNoMoreData() //没有数据结束下拉刷新
                        }
                    }
                    //去掉重复的数据,并根据上拉或下拉来处理数据
                    self.quchong(tmp_order,upordown)

                    //tableview加载数据
                    self.initTableView()
                }
            case false:
                print("异常\(response.result.error)")
                UIAlertController.showAlert(message: "网络连接失败2")
            }
        }
    }


    //去掉重复的数据
    func quchong(_ tmp_order: Array<JSON>,_ upordown: String){
        //总的数据源长度
        let len = self.tableViewData.count
        if len > 0{
            //先循环新的数据(因为是要去除掉老数据中的重复数据,所以先循环新的数据,再循环老的数据,根据新的数据跟每一个老的数据对比,相同的删除掉)
            for (key,item) in tmp_order.enumerated(){
                //循环总的数据
                for (key2,item2) in self.tableViewData.enumerated(){
                    if item != nil && item2 != nil{
                        if item["id"].stringValue == item2[key2]["id"].stringValue{
                            //如果老数据里有相同的新数据,就将老数据删除
                            self.tableViewData.remove(at: key2)
                        }
                    }
                }
            }

        }
        if upordown == "up"{
            //如果是下拉刷新,将老的数据添加到新的数据后面
            self.tableViewData = tmp_order + self.tableViewData
        }else if upordown == "down"{
            //如果是上拉加载,就将新的数据添加到老的数据后面
            self.tableViewData = self.tableViewData + tmp_order
            //移除掉最后一条数据(因为上拉加载更多时,最后一条后有重复,在上面去重的时候最后一条会处理不到)
            self.tableViewData.removeLast()
        }
        print("去重后订单的个数:\(self.tableViewData.count)")
    }

    //第一个参数为要排序的数组,第二个为根据排序的字段,第三个为是否是时间排序
    func jsonSort(_ jsonArray:Array<JSON>,_ field:String,_ isData:Bool) -> Array<JSON>{
        var jary = jsonArray
        //如果数组长度小于2就步排序了
        if jary.count < 2{
            return jary
        }
        //如果是时间排序
        if isData{
            jary.sort { (x, y) -> Bool in
                let formatter = DateFormatter()
                formatter.dateFormat = "yyyyMMddHHmmss"
                let date_str1 = x[field].rawString()
                let date_str2 = y[field].rawString()
                let d1 = formatter.date(from: date_str1!)
                let d2 = formatter.date(from: date_str2!)
                return d1?.compare(d2!) == .orderedDescending //降序排列的 date1 > date2 降序排列 “orderedAscending”代表升序date1 < date2
            }
        }else{
            jary.sort { (x, y) -> Bool in
                //字母排序,数字排序
                return y[field] < x[field]
            }
        }
        return jary
    }


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

图片轮播缺少的类可以参考我的这篇文章
MJRefresh具体用法可以参考这篇文章

使用MJRefresh时候遇到的问题
1.在给上拉刷新和下拉加载配置图片动画效果的时候,图片一定要小,太大的话刷新会失效(这个问题就因为我当时懒得搞图片,触发的,害得我爬了大半天的坑)

猜你喜欢

转载自blog.csdn.net/wa172126691/article/details/80250571
今日推荐