2017-06-09 4 views
1

Ich möchte die Zelle einer Sammlung einzeln mit der API collectionView.insertItems(at:) laden. Es gibt viele Antworten online, die dies erreichen, indem Sie die alpha der Zelle innerhalb von willDisplayCell und andere Methoden, zum Beispiel hier - link animieren. Nichts funktioniert jedoch perfekt. Der Grund für die Verwendung von collectionView.insertItems(at:) ist, dass die Animation bereits eingebaut ist und keine Hacks benötigt werden.iOS - Wägezellen eins nach dem anderen

jedoch collectionView.insertItems(at:) verwenden, erhalte ich Fehler wie:

*** App abgefangene Ausnahme ‚NSInternalInconsistencyException‘, Grund wegen beenden: ‚Ungültige Update: ungültige Anzahl der Elemente im Abschnitt 0. Die Zahl von Artikeln in einem bestehenden Abschnitt nach dem Update (5) muss gleich der Anzahl der Artikel in diesem Abschnitt vor dem Update (5) sein, plus oder minus die Anzahl der Elemente eingefügt oder aus diesem Abschnitt gelöscht (1 eingefügt, 0 gelöscht) und plus oder minus die Anzahl der Artikel in oder ausbewegtdieser Abschnitt (0 eingezogen, 0 ausgezogen).

Dies ist ein Beispiel dafür, was ich habe, ist es, wie oben gezeigt abstürzt, aber es ist ein Anfang ich in der richtigen Richtung denke (hoffentlich):

class ViewController: UIViewController { 

    @IBOutlet weak var collectionView: UICollectionView! 

    /// This array is populated from a network call. 
    let images = [Image]() 

    override func viewDidAppear(_ animated: Bool) { 
     super.viewDidAppear(animated) 

     animateCells() 
    } 

    func animateCells() { 
     let indexPaths = [IndexPath(item: 0, section: 0), 
          IndexPath(item: 1, section: 0), 
          IndexPath(item: 2, section: 0), 
          IndexPath(item: 3, section: 0), 
          IndexPath(item: 4, section: 0)] 

     for indexPath in indexPaths { 
      let delayTime = 0.1 + Double(indexPath.row) * 0.3 

      delay(delayTime) { 
       self.collectionView.performBatchUpdates({ 
        self.collectionView.insertItems(at: [indexPath]) 
       }, completion: nil) 
      } 
     } 
    } 

    func delay(_ delay: TimeInterval, closure: @escaping() -> Void) { 
     let when = DispatchTime.now() + delay 
     DispatchQueue.main.asyncAfter(deadline: when, execute: closure) 
    } 
} 

// MARK: - UICollectionViewDataSource 

extension ViewController: UICollectionViewDataSource { 
    func numberOfSections(in collectionView: UICollectionView) -> Int { 
     return 1 
    } 

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 
     return images.count 
    } 

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 
     let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) 

     return cell 
    } 
} 

Eines der wichtigsten Probleme, die ich sehe, ist dass ich return images.count innerhalb von numberOfItemsInSection mache.

Irgendwelche Gedanken?

+0

Würden Sie bitte wählen Sie eine Antwort als richtig ein, so dass andere Besucher helfen könnte, ihren Fehler zu finden. –

+0

@GovindPrajapati Haben noch nicht Antworten ausprobiert, wird bald! – JEL

Antwort

1

machte ich eine Demo mit Ihrem Code und fand Ihren Fehler

Wenn Sie Elemente in Ihrer Sammlung Ansicht einfügen gibt es bereits 5 Elemente in Ihrer Sammlung Ansicht in dieser Position, so dass Sie nicht einfügen neue Zellen dort, weil Ihr Bilder-Array nur 5 Elemente enthält, die bereits angezeigt wurden.

finden Sie unter Arbeitscode ->

class ViewController: UIViewController { 

    @IBOutlet weak var collectionView: UICollectionView! 

    //Array for collectionView 
    var images :[UIImage] = [] 

    //This array will populate from network call 
    var arrAllImagesFromNetwork : [UIImage] = Array(repeating: UIImage(named: "img1")!, count: 5) 

    override func viewDidAppear(_ animated: Bool) { 
     super.viewDidAppear(animated) 

     animateCells() 

    } 

    func animateCells() { 
     let indexPaths = [IndexPath(item: 0, section: 0), 
          IndexPath(item: 1, section: 0), 
          IndexPath(item: 2, section: 0), 
          IndexPath(item: 3, section: 0), 
          IndexPath(item: 4, section: 0)] 



     for indexPath in indexPaths { 
      let delayTime = 0.1 + Double(indexPath.row) * 0.3 

      delay(delayTime) { 

       self.images.append(self.arrAllImagesFromNetwork[indexPath.row]) 

       self.collectionView.performBatchUpdates({ 
        self.collectionView.insertItems(at: [indexPath]) 
       }, completion: nil) 
      } 
     } 
    } 

    func delay(_ delay: TimeInterval, closure: @escaping() -> Void) { 
     let when = DispatchTime.now() + delay 
     DispatchQueue.main.asyncAfter(deadline: when, execute: closure) 
    } 
} 

// MARK: - UICollectionViewDataSource 

extension ViewController: UICollectionViewDataSource { 
    func numberOfSections(in collectionView: UICollectionView) -> Int { 
     return 1 
    } 

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 
     return images.count 
    } 

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 
     let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) 

     return cell 
    } 
} 
+0

Warum machst du 'self.images.append (indexPath.row)'? Das Array 'images' ist für ein tatsächliches Objekt, ich habe meinen Code geändert, um dies deutlicher zu machen, indem ich' let images = [Image]() 'mache. Entschuldigung, wenn es nicht klar war. Funktioniert diese Antwort noch? – JEL

+0

Zu diesem Zweck nehmen Sie zwei Arrays eins, um alle Bilder aus Netzwerkaufruf zu speichern, und eins, um die Sammlungsansicht aufzufüllen. Bitte werfen Sie einen Blick auf die bearbeitete Antwort. –

+0

Danke! Es klappt – JEL

1

Haben Sie versucht, das Element auch mit Verzögerung an images anzuhängen?

var images = Array(repeating: 0, count: 0) 

delay(delayTime) { 
    self.collectionView.performBatchUpdates({ 
       self.images.append(0)  
       self.collectionView.insertItems(at: [indexPath]) 
    }, completion: nil) 
} 
+0

Wäre es besser, wenn zwei verschiedene Arrays irgendwie zusammenarbeiten würden? Anstatt an das tatsächliche Array "anzufügen", nicht sicher – JEL

+0

Könnten Sie Ihren Code bitte umformulieren, um tatsächliche Objekte zu verwenden? Ich habe meine Frage aktualisiert, um klarer zu sein, statt "var images = Array (repeating: 0, count: 10)" habe ich nun "let images = [Image]()'. Das Array von 'Image's kommt von einem Netzwerkanruf. – JEL

Verwandte Themen