it-swarm.com.de

Wie kann ich überprüfen, ob ein indexPath gültig ist, und so den Fehler "zu ungültigem Indexpfad scrollen" vermeiden?

Wie kann ich überprüfen, ob ein indexPath gültig ist oder nicht?

Ich möchte zu einem Indexpfad blättern, erhalte jedoch manchmal eine Fehlermeldung, wenn die Unteransichten meiner Sammlungsansicht nicht vollständig geladen sind.

26
webmagnets

Sie könnten es überprüfen

- numberOfSections
- numberOfItemsInSection: 

von Ihrem UICollection​View​Data​Source, um zu sehen, ob Ihr Indexpfad ein gültiger ist.

30
muffe

Eine prägnantere Lösung?

func indexPathIsValid(indexPath: NSIndexPath) -> Bool {
    if indexPath.section >= numberOfSectionsInCollectionView(collectionView) {
        return false
    }
    if indexPath.row >= collectionView.numberOfItemsInSection(indexPath.section) {
        return false
    }
    return true
}

oder kompakter, aber weniger lesbar ...

func indexPathIsValid(indexPath: NSIndexPath) -> Bool {
    return indexPath.section < numberOfSectionsInCollectionView(collectionView) && indexPath.row < collectionView.numberOfItemsInSection(indexPath.section)
}
16
Andres Canella

@ ABakerSmiths Antwort ist knapp, aber nicht ganz richtig.

Die Antwort hängt von Ihrem Modell ab. 

Wenn Sie eine Sammelsicht mit mehreren Abschnitten (oder Tabellenansicht für dasselbe Problem - dasselbe Problem) haben, ist es üblich, ein Array von Arrays zum Speichern Ihrer Daten zu verwenden.

Das äußere Array enthält Ihre Abschnitte, und jedes innere Array enthält die Zeilen für diesen Abschnitt.

Du könntest so etwas haben:

struct TableViewData
{
  //Dummy structure, replaced with whatever you might use instead
  var heading: String
  var subHead: String
  var value: Int
}

typealias RowArray: [TableViewData]

typeAlias SectionArray: [RowArray]


var myTableViewData: SectionArray

In diesem Fall müssten Sie bei Anzeige eines indexPath Ihr Modellobjekt abfragen (myTableViewData, im obigen Beispiel).

Der Code könnte so aussehen:

func indexPathIsValid(theIndexPath: NSIndexPath) -> Bool
{
  let section = theIndexPath.section!
  let row = theIndexPath.row!
  if section > myTableViewData.count-1
  {
    return false
  }
  let aRow = myTableViewData[section]
  return aRow.count < row
}

BEARBEITEN:

@ABakerSmith hat eine interessante Wendung: Die Datenquelle fragen. Auf diese Weise können Sie eine Lösung schreiben, die unabhängig vom Datenmodell funktioniert. Sein Code ist nahe, aber immer noch nicht ganz richtig. Es sollte wirklich so sein:

func indexPathIsValid(indexPath: NSIndexPath) -> Bool 
{
  let section = indexPath.section!
  let row = indexPath.row!

  let lastSectionIndex = 
    numberOfSectionsInCollectionView(collectionView) - 1

  //Make sure the specified section exists
  if section > lastSectionIndex
  {
    return false
  }
  let rowCount = self.collectionView(
    collectionView, numberOfItemsInSection: indexPath.section) - 1

  return row <= rowCount
}
11
Duncan C

Hier ist ein Swift 4-Snippet, das ich geschrieben und seit einiger Zeit verwendet habe. Sie können entweder nur zu einem IndexPath blättern, wenn dieser verfügbar ist, oder - einen Fehler ausgeben, wenn der IndexPath nicht verfügbar ist, um zu steuern, was Sie in dieser Situation tun möchten. 

Check den Code hier:

https://Gist.github.com/freak4pc/0f244f41a5379f001571809197e72b90

Sie können entweder

myCollectionView.scrollToItemIfAvailable(at: indexPath, at: .top, animated: true)

Oder 

myCollectionView.scrollToItemOrThrow(at: indexPath, at: .top, animated: true)

Letzteres würde so etwas werfen: 

expression unexpectedly raised an error: IndexPath [0, 2000] is not available. The last available IndexPath is [0, 36]

4
Shai Mishali

Verwendung der Swift-Erweiterung:

extension UICollectionView {

  func validate(indexPath: IndexPath) -> Bool {
    if indexPath.section >= numberOfSections {
      return false
    }

    if indexPath.row >= numberOfItems(inSection: indexPath.section) {
      return false
    }

    return true
  }

}

// Usage
let indexPath = IndexPath(item: 10, section: 0)

if sampleCollectionView.validate(indexPath: indexPath) {
  sampleCollectionView.scrollToItem(at: indexPath, at: UICollectionViewScrollPosition.centeredHorizontally, animated: true)
}
3
Ashok Kumar S

Sie sollten die Validierung der Indexpfade überprüfen, an die die Datenquelle angehängt wird (zukünftiger Status), und das Löschen der Indexpfade mit den aktuell vorhandenen (aktueller Status).

extension UITableView {

func isValid(indexPath: IndexPath, inDataSource: Bool = false) -> Bool {
    guard
        let numberOfSections = inDataSource
            ? dataSource?.numberOfSections?(in: self)
            : numberOfSections,
        let numberOfRows = inDataSource
            ? dataSource?.tableView(self, numberOfRowsInSection: indexPath.section)
            : numberOfRows(inSection: indexPath.section)
    else {
        preconditionFailure("There must be a datasource to validate an index path")
    }
    return indexPath.section < numberOfSections && indexPath.row < numberOfRows
}

verwendungszweck:

// insert    
tableView.insertRows(at: indexPaths.filter({ tableView.isValid(indexPath: $0, inDataSource: true) }), with: .top)

// remove
tableView.deleteRows(at: indexPaths.filter({ tableView.isValid(indexPath: $0) }), with: .top)

ausgabe:

true or false
0
Lloyd Keijzer

Wenn Sie versuchen, den Status einer Zelle in der Sammlungsansicht festzulegen, ohne zu wissen, ob der Indexpfad gültig ist oder nicht, können Sie versuchen, die Indizes für Zellen mit einem speziellen Status zu speichern und den Status der Zellen beim Laden festzulegen.

0
carrotzoe

Ziel C-Version:

- (BOOL)indexPathIsValid:(NSIndexPath *)indexPath
{
    return indexPath.section < [self.collectionView numberOfSections] && indexPath.row < [self.collectionView numberOfItemsInSection:indexPath.section];
}
0
wzbozon