Swift tableView分页

Swi*_*per 47 pagination uitableview ios swift

我用json解析代码成功地工作tableview.但是可能还有1000个项目,因此在滚动底部时需要分页.我不知道我怎么能在下面做我的代码.对于objective-c有很多例子但是对于swift我没有找到工作的例子.我在等你的帮助.我想会帮助太多人.谢谢 !

import UIKit

class ViewController: UIViewController, UITableViewDataSource,UITableViewDelegate {

    let kSuccessTitle = "Congratulations"
    let kErrorTitle = "Connection error"
    let kNoticeTitle = "Notice"
    let kWarningTitle = "Warning"
    let kInfoTitle = "Info"
    let kSubtitle = "You've just displayed this awesome Pop Up View"


    @IBOutlet weak var myTableView: UITableView!
    @IBOutlet weak var myActivityIndicator: UIActivityIndicatorView!

    var privateList = [String]()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

    }

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)

        loadItems()

    }

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


    internal func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
    {
        return privateList.count
    }




    internal func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
    {

       let cell:myCell = tableView.dequeueReusableCellWithIdentifier("myCell") as! myCell

        cell.titleLabel.text = privateList[indexPath.row]


        return cell
    }


    func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {

        if (editingStyle == UITableViewCellEditingStyle.Delete){

         print(indexPath.row)


            let alert = SCLAlertView()
            alert.addButton("Hay?r"){ }
            alert.addButton("Evet") {

                self.myTableView.beginUpdates()

                 self.privateList.removeAtIndex(indexPath.row)
                tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Left)
                print("Silindi")

                self.myTableView.endUpdates()

                  self.loadItems()

            }
            alert.showSuccess(kSuccessTitle, subTitle: kSubtitle)

        }


    }





    func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
        // the cells you would like the actions to appear needs to be editable
        return true
    }



    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {


        if(segue.identifier == "Detail") {

            let destinationView = segue.destinationViewController as! DetailViewController

            if let indexPath = myTableView.indexPathForCell(sender as! UITableViewCell) {

                destinationView.privateLista = privateList[indexPath.row]

            }
        }
    }



    internal func tableView(tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat
    {
        return 0.0
    }


    func loadItems()
    {
     loadItemsNow("privateList")

    }

    func loadItemsNow(listType:String){
        myActivityIndicator.startAnimating()
        let listUrlString =  "http://bla.com/json2.php?listType=" + listType + "&t=" + NSUUID().UUIDString
        let myUrl = NSURL(string: listUrlString);
        let request = NSMutableURLRequest(URL:myUrl!);
        request.HTTPMethod = "GET";

        let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
            data, response, error in

            if error != nil {
                print(error!.localizedDescription)
                dispatch_async(dispatch_get_main_queue(),{
                    self.myActivityIndicator.stopAnimating()
                })

                return
            }


            do {

                let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as? NSArray

                if let parseJSON = json {


                        self.privateList = parseJSON as! [String]

                }

            } catch {
                print(error)

            }

            dispatch_async(dispatch_get_main_queue(),{
                self.myActivityIndicator.stopAnimating()
                self.myTableView.reloadData()
            })


        }

        task.resume()
    }


}
Run Code Online (Sandbox Code Playgroud)

War*_*shi 56

为此,您还需要进行服务器端更改.

  1. 服务器将接受fromIndexbatchSizeAPIurl中作为查询参数.

    let listUrlString =  "http://bla.com/json2.php?listType=" + listType + "&t=" + NSUUID().UUIDString + "&batchSize=" + batchSize + "&fromIndex=" + fromIndex
    
    Run Code Online (Sandbox Code Playgroud)
  2. 在服务器响应中,将有一个额外的密钥totalItems.这将用于识别是否收到所有项目.阵列或项目fromIndexbatchSize项目数.

在应用程序方面

  1. 首先loadItem()将使用fromIndex = 0batchSize = 20(例如in viewDidLoad()viewWillAppear)调用.在第一次privateList调用之前从数组中删除所有项目loadItem()

  2. 服务器返回前20个项目的数组和totalItems服务器中的项目总数.

  3. privateList数组中追加20个项目并重新加载tableView

  4. tableView:cellForRowAtIndexPath方法中检查单元格是否是最后一个单元格.并检查totalItems(表单服务器)是否大于privateList.count.这意味着服务器中有更多项目要加载

    if indexPath.row == privateList.count - 1 { // last cell
        if totalItems > privateList.count { // more items to fetch
            loadItem() // increment `fromIndex` by 20 before server call
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

题: where is refresh ? will be scrolling ?

收到服务器响应后,在数组中追加新项目后刷新.(第3步)

tableView:cellForRowAtIndexPath当用户滚动时,滚动将触发每个单元格.代码正在检查它是否是最后一个单元格并获取剩余项目.(第4步)

添加了示例项目:https:
//github.com/rishi420/TableViewPaging

  • @SwiftDeveloper 答案更新为示例项目链接。下载、运行并查看“打印”日志。 (2认同)
  • :) 给我一个示例 url `http://bla.com/json2.php?listType=...` 我可以点击并测试 (2认同)

Mah*_*iri 14

做的好和有效的方法是使用scrollviewDelegate在tableview中只需添加UIScrollViewDelegate在您viewController 在视图控制器

//For Pagination
var isDataLoading:Bool=false
var pageNo:Int=0
var limit:Int=20
var offset:Int=0 //pageNo*limit
var didEndReached:Bool=false
viewDidLoad(_){
tableview.delegate=self //To enable scrollviewdelegate
}
Run Code Online (Sandbox Code Playgroud)

覆盖此委托中的两个方法

func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {

        print("scrollViewWillBeginDragging")
        isDataLoading = false
    }



    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        print("scrollViewDidEndDecelerating")
    }
    //Pagination
    func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {

            print("scrollViewDidEndDragging")
            if ((tableView.contentOffset.y + tableView.frame.size.height) >= tableView.contentSize.height)
            {
                if !isDataLoading{
                    isDataLoading = true
                    self.pageNo=self.pageNo+1
                    self.limit=self.limit+10
                    self.offset=self.limit * self.pageNo
                    loadCallLogData(offset: self.offset, limit: self.limit)

                }
            }


    }
Run Code Online (Sandbox Code Playgroud)


Mhm*_*izk 12

SWIFT 3.0 - 4 ......

如果您要在API请求中发送页码,那么这是在您的应用中实施分页的理想方式.

1)声明具有初始值0的变量current Page和bool,以检查是否正在加载任何列表,初始值为false

var currentPage : Int = 0
var isLoadingList : Bool = false
Run Code Online (Sandbox Code Playgroud)

2)这是获取列表示例的函数:

 func getListFromServer(_ pageNumber: Int){
 self.isloadingList = false
 self.table.reloadData()
 } 
Run Code Online (Sandbox Code Playgroud)

3)这是增加页码并调用API函数的函数

 func loadMoreItemsForList(){
 currentPage += 1
 getListFromServer(currentPage)
 }
Run Code Online (Sandbox Code Playgroud)

4)这是scrollView滚动时将调用的方法

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    if (((scrollView.contentOffset.y + scrollView.frame.size.height) > scrollView.contentSize.height ) && ! isLoadingList){
        self. isLoadingList = true
        self. loadMoreItemsForList()
    }
}
Run Code Online (Sandbox Code Playgroud)

PS bool isLoadingList的作用是防止滚动视图在一次拖动中获取更多列表到表视图的底部.

  • 没有 reloadData() 不会滚动到顶部,使用 `tableView.scrollToRow(at: IndexPath(row: 0, section: 0), at: .top , animation: true)` 滚动到顶部 (2认同)

Pau*_*son 10

在iOS10中添加新协议现在更容易一些: UITableViewDataSourcePrefetching

https://developer.apple.com/documentation/uikit/uitableviewdatasourceprefetching

  • 这应该是公认的答案。这是关于如何使用此协议的很好的教程:https://www.raywenderlich.com/5786-uitableview-infinite-scrolling-tutorial。 (2认同)

小智 6

//It works fine 
func getPageCount(TotalCount : Int) -> Int{
    var num = TotalCount
    let reminder = num % 50
    print(reminder)
    if reminder != 0{
        num = TotalCount/50
        num = num + 1

    }else{
        num = TotalCount/50
    }
    return num
}

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    let TotalPage =  self.getPageCount(TotalCount: Int(Datacount)!)
    let lastItem = self.mainArr.count - 1
    if indexPath.row == lastItem {
        print("IndexRow\(indexPath.row)")
        if self.page < TotalPage-1 {
            self.view_Loader.isHidden = false
            self.view_LoaderHeight.constant = 50
        self.page += 1
        self.YourAPI()
        }
    }
}`
Run Code Online (Sandbox Code Playgroud)


Far*_*dov 5

通过使用UITableViewDelegate,您可以调用该函数

   func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    let lastItem = self.mes.count - 1
    if indexPath.row == lastItem {
        print("IndexRow\(indexPath.row)")
        if currentPage < totalPage {
            currentPage += 1
           //Get data from Server
        }
    }
}
Run Code Online (Sandbox Code Playgroud)