2016-11-19 15 views
2

Ich habe diesen seltsamen App-Absturz beim Ziehen zum Aktualisieren auftritt.Schwerwiegender Fehler: Index außerhalb des Bereichs beim Aktualisieren der Tabellenansicht

Mein Code geht wie folgt:

var posts: [Posts] = [] 

override func viewDidLoad() { 
    super.viewDidLoad() 

    // refreshControl -> pull to refresh handler 
    let refreshControl = UIRefreshControl() 
    refreshControl.addTarget(self, 
          action: #selector(Main_TVC.getData), 
          for: UIControlEvents.valueChanged) 
    self.refreshControl = refreshControl 

    getData() 
} 

override func numberOfSections(in tableView: UITableView) -> Int { 
    return 1 
} 

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
    return posts.count 
} 

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", 
              for: indexPath) as! PostsTableViewCell 

    cell.titleLabel.text = posts[indexPath.row].postTitle 
    cell.bodyLabel.text = posts[indexPath.row].postBody 

    return cell 
} 

func getData() { 
    self.posts.removeAll() 

    // queries the backend and fills the data - sorry for code omission 

    refresh() 

} 


func refresh() { 
    self.tableView.reloadData() 
    self.refreshControl?.endRefreshing() 
} 

Die App läuft richtig und auch wenn ich refresh nach unten ziehen zu, alles läuft perfekt, aber wenn ein lange nach unten ziehen zu aktualisieren tun, wie unten fast ziehen schlagen die Unterseite des Bildschirms, die app abstürzt und fordert den folgenden Fehler:

fatale Fehler: Index außerhalb des Bereichs

auf der Linie

cell.titleLabel.text = Beiträge [indexPath.row] .postTitle

Wenn ich die Post-Zähler und die indexPath drucken, wie folgt:

print ("posts.count = (Beiträge. count) ") print (" indexPath.row = (indexPath.row) ")

Als ich in der normalen Art und Weise bin nach unten ziehen, es druckt die korrekten Daten, aber wenn ich nach unten ziehen, wie ein langer Zug, durch den gesamten Bildschirm, wenn dies beim Absturz angezeigt wird s

posts.count = 0

indexPath.row = 2

Diese Art der Sache geschehen ist mir noch nie die refreshControl mit der Art, wie ich hier bin mit.

Hope meine Informationen sind verständlich, vor allem auf den langen Pull zu aktualisieren Problem.

+0

a) könnte aktualisieren() mehr als einmal ausgelöst werden (ich bezweifle es, aber nur bestätigen).b) Wie manipulierst du die Datenquelle in deinem weggelassenen Code? –

Antwort

7

Ihr Problem ist, dass das erste, was Sie in getData tun ist, alle der Beiträge von self.posts entfernen, aber Sie nicht (vermutlich seit Code fehlt) die Tabellenansicht neu zu laden, so dass nun die Anzahl der Stellen in der Anordnung (0) und die Anzahl der Posts, die das Tableview * im Array findet (nicht null), ist anders, so dass Sie einen Absturz des Array-Bereichs bekommen.

Aufruf reloadData nach self.posts.removeAll() würde das Problem beheben, sondern ‚blinkt‘ führt in der Tableview als es leer Grenzziehung und Grenzziehung dann mit den neuen Daten.

Da Sie nicht den vollständigen Code für getData gezeigt haben, kann ich den genauen Code nicht, die Sie benötigen, aber es sollte etwas sein wie:

func getData() { 
    fetchPostsWithCompletion() { 
     if let tempPosts = dataFromNetwork { 
      self.posts = tempPosts 
     } else { 
      self.posts.removeAll() 
     } 
     self.refresh()  // Dispatch this on the main queue if your completion handler is not already on the main queue 
    } 
} 

Auf diese Weise können die Unterstützung Array nicht manipulieren bis du die neuen Daten hast.

+0

OMG ... du bist der Pate: D Das hat mein Problem gelöst –

+0

Ich frage mich, wo genau der Fehler auftritt. Welche von der tableView aufgerufene Funktion gibt ein unerwartetes Ergebnis zurück? Wäre es nicht zuerst 'tableView (_ :, numberOfRowsInSection:)' vor allem anderen aufzurufen? – Marmelador

+0

Ich erklärte dies im ersten Absatz. Nach dem ersten Aufruf ruft die Tabellenansicht "numberOfRowsInSection" nur auf, wenn angegeben wird, dass sich die Anzahl der Zeilen geändert hat, entweder durch Aufrufen von 'reload' oder Löschen/Einfügen von Zeilen; Wenn Sie das Quell-Array ändern, ohne eine dieser Methoden aufzurufen, besteht nun eine Inkonsistenz zwischen dem Daten-Array und der Anzahl der Zeilen, die der Tabellenansicht im Daten-Array mitgeteilt wurde. – Paulw11

0

Ich hatte gerade das gleiche Problem. Mein Befund ist, dass die Verzögerung der Ausführung von removeAll() auf dem posts Array die Tabellenansicht auf seinem count aktualisiert werden kann.

func getData() { 
    self.delayExecutionByMilliseconds(500) { 
     self.posts.removeAll() 
    } 
    // queries the backend and fills the data - sorry for code omission 

    refresh() 
} 

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

Sie müssen vorsichtig mit Verzögerungen bei der Abfrage des Servers sein. Ich hatte einmal Probleme damit, weil das Netzwerk nicht konstant ist. Wie auch immer, ich bin froh, dass Ihre Lösung Ihr Problem gelöst hat. –

Verwandte Themen