'RefreshControl'上的'数组索引超出范围'

时间:2015-12-18 14:50:26

标签: ios swift uitableview

我有一个TableView,我从api获取数据。抓取/显示数据和分页/无限滚动一切正常。但是,当我尝试使用我的RefreshControl时,它崩溃并出现错误:

  

数组索引超出范围

 var theRefreshControl: UIRefreshControl!
 var results: [JSON]! = []
    // more stuff..

 func refresh(sender: AnyObject) {
        if isFirstLoad == false {
            self.results = []
            currentPage = 1
            getPosts()
        }
        self.theRefreshControl.endRefreshing()
    }

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

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

    cell.delegate = self

    print(indexPath.row) // check below.

    let post = self.results![indexPath.row]    // 'array index out of range' here.

 }

要详细了解错误,我尝试添加print(indexPath.row)。我收到的是,我在第一次加载时从0收到10,然后一刷新,就会变得奇怪:

enter image description here

另外,当我点击(i):

  

{length = 2,path = 0 - 9}

有趣的是,完全相同的方法适用于我的其他TableViewControllers,只有这一个是错误的。可能是什么问题?

func getPosts() {
    isLoading = true

Alamofire.request(.GET, link & params: ["page":"\(currentPage ?? 1)"])
  .responseJSON { response in

      // error checks

    if let data = json["data"].arrayValue as [JSON]? {

        self.lastPage = json["last_page"].int!
        self.currentPage = json["current_page"].int!

        if self.currentPage == 1 {
           self.results = data
           self.tableView.reloadData() 
        } else {                             
           var currentCount = self.results!.count;
           var indxesPath : [NSIndexPath] = [NSIndexPath]()

           for result in data {
             indxesPath.append(NSIndexPath(forRow:currentCount,inSection:0));
              self.results?.append(result)
              currentCount++
           }

     self.tableView.insertRowsAtIndexPaths(indxesPath, withRowAnimation: UITableViewRowAnimation.Bottom)                       
    }

修改:请注意,我在刷新按钮操作功能中尝试了results.removeAll()以及results.removeAll(keepCapacity: false),但没有运气。我仍然得到相同的错误和相同的日志`print(indexPath.row) - 0到10在第一次加载,并在刷新,奇怪的是,6,7,8,[],9

4 个答案:

答案 0 :(得分:2)

Swift 3.0 - 这里的问题相同,以类似于@mcclux的方式解决,但步骤少了一步。

使用内置的UIRefreshControl。 insert into personnel (`name`) values("'hi'"); insert into personnel (`name`) values("'hello'"); select * from personnel where `name` != "'hi'" ,然后在viewDidLoad中配置它:

var refreshControl: UIRefreshControl!

然后,您可以使用

将代码包装在cellForRowAt indexPath中

refreshControl = UIRefreshControl.init() refreshControl.attributedTitle = NSAttributedString(string: "Pull to refresh") refreshControl.addTarget(self, action: #selector(yourViewControllerName.yourFunctionToCallOnRefresh), for: UIControlEvents.valueChanged) tableView.addSubview(refreshControl)

在经历了几个小时的挣扎之后,我完美地为我工作。希望这有帮助!

答案 1 :(得分:1)

我有类似的问题;它是在我的情况下由于在刷新期间调用tableView,在重置内容期间引起的。由于索引在一段时间内是空的,因此应用程序偶尔会将索引抛出范围。它并非每次都发生。我通过创建一个boolean var(isRefreshing)来解决它,当刷新开始时它被设置为true,然后在刷新结束后设置为false。在tableView()内部,我有一个功能包装器。在你的情况下,它看起来像:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    if !self.isRefreshing {
        let cell : PostCell = tableView.dequeueReusableCellWithIdentifier("PostCell") as! PostCell
        cell.delegate = self
        print(indexPath.row) // check below.
        let post = self.results![indexPath.row]    // 'array index out of range' here.
    }
 }

编辑:这是我如何使用它。单元格创建和返回位于if:

之外
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("SessionTableViewCell", forIndexPath: indexPath) as! SessionTableViewCell
    if !self.isReloading {
            ...
    }
    return cell
}

答案 2 :(得分:0)

当支持数组被清空时,我遇到了类似的问题,就像你用self.results = []做的那样。在我的发现中,还有2种方法可以解决这个问题。

//1. is to reload table view as soon as you empty the array

 func refresh(sender: AnyObject) {
    if isFirstLoad == false {
        self.results = []
        self.tableView.reloadData()
        currentPage = 1
        getPosts()
    }
    self.theRefreshControl.endRefreshing()
}

//2. is to delay the execution of the code inside the if scope to give enough time for the table view to get up to date on the count of the results array

  func refresh(sender: AnyObject) {
     if isFirstLoad == false {
        self.delayExecutionByMilliseconds(500) {
           self.results = []
           currentPage = 1
           getPosts()
        }
     }
     self.theRefreshControl.endRefreshing()
  }

  func delayExecutionByMilliseconds(_ delay: Int, for anonFunc: @escaping () -> Void) {
     let when = DispatchTime.now() + .milliseconds(delay)
     DispatchQueue.main.asyncAfter(deadline: when, execute: anonFunc)
  }

答案 3 :(得分:0)

在刷新功能中,清理阵列后,在函数getPosts()之前添加self.tableView.reloadData()