2016-01-15 4 views
0

ИНОГДА ОБНОВЛ РАБОТУ ИНОГДА НЕSwift 2 + Анализировать: Индекс массива вне диапазона

У меня есть UITableViewController, который является в основном лентой новостей. Я также реализовал функцию обновления для обновления. Однако иногда, когда я пытаюсь обновить, это дает мне ошибку

«Индекс массива за пределами допустимого диапазона».

Я знаю, что это означает, что предмет, который он пытается получить, не существует, но можете ли вы сказать мне, почему? Вот мой код:

override func viewDidLoad() { 
    super.viewDidLoad() 

    refresher = UIRefreshControl() 
    refresher.attributedTitle = NSAttributedString(string: "Pull to refresh") 
    refresher.addTarget(self, action: "refresh", forControlEvents: UIControlEvents.ValueChanged) 
    self.tableView.addSubview(refresher) 
    refresh() 

    tableView.delegate = self 
    tableView.dataSource = self 
} 

и обновление функции():

func refresh() { 

    //disable app while it does stuff 
    UIApplication.sharedApplication().beginIgnoringInteractionEvents() 

    //get username and match with userId 
    let getUser = PFUser.query() 
    getUser?.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in 

     if let users = objects { 

      //clean arrays and dictionaries so we dont get indexing error??? 
      self.messages.removeAll(keepCapacity: true) 
      self.users.removeAll(keepCapacity: true) 
      self.usernames.removeAll(keepCapacity: true) 

      for object in users { 

       if let user = object as? PFUser { 

        //make userId = username 
        self.users[user.objectId!] = user.username! 
       } 
      } 
     } 
    }) 

    let getPost = PFQuery(className: "Posts") 
    getPost.findObjectsInBackgroundWithBlock { (objects, error) -> Void in 

     if error == nil { 
     if let objects = objects { 

      self.messages.removeAll(keepCapacity: true) 
      self.usernames.removeAll(keepCapacity: true) 

      for object in objects { 

       self.messages.append(object["message"] as! String) 
       self.usernames.append(self.users[object["userId"] as! String]!) 

       self.tableView.reloadData() 
      } 
     } 
     } 
    } 

    self.refresher.endRefreshing() 
    UIApplication.sharedApplication().endIgnoringInteractionEvents() 
} 

и:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 
    let myCell = tableView.dequeueReusableCellWithIdentifier("SinglePostCell", forIndexPath: indexPath) as! PostCell 


    //ERROR GETS REPORTED ON THE LINE BELOW 
    myCell.usernamePosted.text = usernames[indexPath.row] 
    myCell.messagePosted.text = messages[indexPath.row] 

    return myCell 
} 

ответ

0

Я считаю, что в self.users[user.objectId!] = user.username! user.ObjectId некоторая случайная величина, присвоенная parse, который выглядит так: «34xcf4». Вот почему вы можете получить 'Array index out of range'.

0

Есть два необходимые методы для конфигурирования UITableView:

  • tableView(_:cellForRowAtIndexPath:) и
  • tableView(_:numberOfRowsInSection:)

В своем коде вы представляете только один необходимый метод, если вы не реализуйте второй метод, а затем он может вызвать ошибки.

Проверьте документацию по адресу: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableViewDataSource_Protocol/#//apple_ref/occ/intfm/UITableViewDataSource/tableView:cellForRowAtIndexPath:

1

У вас есть состояние гонки дали вы делаете две фоновые задачи, где вторая зависит от значения, возвращаемые из первого. getUser?.findObjectsInBackgroundWithBlock немедленно вернется, и начнется выполнение getPost.findObjectsInBackgroundWithBlock. GetPost должен быть внутри блока для getUser, чтобы гарантировать правильность последовательности. Аналогично, следующие две строк должны быть внутри вторым блок:

self.refresher.endRefreshing() 
UIApplication.sharedApplication().endIgnoringInteractionEvents() 

Учитывая линию ошибки, вы, вероятно, также есть условие гонки между двумя фоновыми задачами и отображениями Tableview. Я был бы склонен попробовать:

func tableView(tableView:UITableView!, numberOfRowsInSection section:Int) { 
    return self.refresher.refreshing ? 0 : self.usernames.count 
} 

Таким образом, вы не будете трогать self.usernames пока фоновое обновление не будет завершено (до тех пор, как вы помните, чтобы положить endRefreshing внутри второго блока, который также положить внутри первого блока).

0

Вы вызываете self.tableView.reloadData() для каждого добавления в ваш массив и делаете это в фоновом потоке.

Как правило, вы не должны делать обновления пользовательского интерфейса в фоновом потоке. Когда вы очищаете себя и себя.usernames, потому что вы находитесь в фоновом потоке, ничто не мешает tableview пытаться получить ячейку по индексу, у которого больше нет данных в массиве.

Если вы хотите сохранить код в фоновом потоке (насколько это может быть опасно), вы должны хотя бы позвонить .beginUpdates, прежде чем перезагружать свои массивы и ждать, пока они все не будут выполнены до вызова reload и endUpdates.

Смежные вопросы