UICollectionView reloadData non funziona correttamente in iOS 7

Ho fatto l’aggiornamento il mio applicazioni per funzionare su iOS 7, che sta andando senza problemi per la maggior parte. Ho notato in più di una app che reloadData metodo di UICollectionViewController non agisce piuttosto come una volta.

Mi faccio carico il UICollectionViewController, compilare il UICollectionView con alcuni dati, come normale. Questo funziona alla grande il primo tempo. Tuttavia, se ho la richiesta di nuovi dati (compilare il UICollectionViewDataSource), e quindi chiamare reloadData, sarà query origine dati per numberOfItemsInSection e numberOfSectionsInCollectionView, ma non mi sembra di chiamare cellForItemAtIndexPath il numero corretto di volte.

Se cambio il codice solo per ricaricare una sezione, quindi dovrebbe funzionare correttamente. Questo non è un problema per me per cambiare questi, ma non credo che io debba. reloadData deve ricaricare tutte le celle visibili in base alla documentazione.

Chiunque altro ha visto questo?

  • Stesso qui, in iOS7GM, ha funzionato bene prima. Ho notato che chiamando reloadData dopo il viewDidAppear sembra risolvere il problema, la sua orribile soluzione, e ha bisogno di correzione. Spero che qualcuno mi aiuta qui.
  • Avendo lo stesso problema. Il codice utilizzato per lavorare bene in iOS6 . ora non si chiama cellforitematindexpath anche se il ritorno adeguato numero di cellule
  • Era fisso in un post-release 7.0?
  • Sto ancora affrontando le questioni relative a questo problema.
  • Problema simile dopo la modifica [collectionView setFrame] on-the-fly; sempre annulla una cella e basta, indipendentemente dal numero nell’origine dati. Provato di tutto e di più, e non è possibile ottenere intorno ad esso.
  • Penso che si fissa in 7.1
  • Ho lo stesso problema in IOS 9.2, @jasonIM ‘s soluzione risolve il mio problema. ma nel mio caso, viewWillAppear è utile.
  • Ho, inoltre, di avere problemi con reloadData in realtà non l’aggiornamento di tutti delle cellule, anche se il numberOfItemsInSection è cambiato. Questo è con iOS 9.3. La soluzione era di spedizione async la ricarica dati nel thread principale in modo che venga eseguito al successivo avvio ciclo.

 

17 Replies
  1. 71

    Forza di questo nel thread principale:

    dispatch_async(dispatch_get_main_queue(), ^ {
        [self.collectionView reloadData];
    });
    • Sei il benvenuto a spiegare di più..
    • Io non sono sicuro se posso spiegare di più. Dopo la ricerca, la ricerca, la sperimentazione e la tastatura. Sento che questo è un iOS 7 bug. Costringendo il thread principale di esecuzione tutti UIKit relativi messaggi. Mi sembra di correre in questo momento popping alla vista da un altro punto di vista controller. Io di aggiornare i dati sul viewWillAppear. Ho potuto vedere i dati e visualizzazione di raccolta di ricarica chiamata, ma l’interfaccia utente non è stato aggiornato. Costretto il thread principale (UI thread), e magicamente inizia a lavorare. Questo è solo in IOS 7.
    • Non ha molto senso, perché non si può chiamare reloadData di thread principale (non è possibile aggiornare vista del thread principale) in modo che questo forse è un effetto collaterale che si traduce in ciò che si vuole, a causa di alcune condizioni di gara.
    • Spedizione sui principali coda la coda principale solo ritardi di esecuzione fino al prossimo run loop, permettendo a tutto ciò che è attualmente in coda la possibilità di eseguire prima.
    • Grazie!! Ancora non capisco se Joony argomento è corretto perché i dati principali della richiesta di consumare tempo e la risposta è in ritardo o perché ho ricaricato i dati in willDisplayCell.
    • non ha funzionato per me 🙁
    • Wow tutto questo tempo e questo è ancora in piedi. Questa è infatti una condizione di competizione, o relativi all’evento di visualizzazione del ciclo di vita. vista “” appare sarebbe stato già disegnato. Buona conoscenza Joony, Grazie. Credo che si possa impostare questa voce su “risposto” finalmente?

  2. 63

    Nel mio caso, il numero di cellule/sezioni in origine non è mai cambiato e volevo ricaricare il contenuto visibile sullo schermo..

    Sono riuscito a ottenere intorno a questo, chiamando:

    [self.collectionView reloadItemsAtIndexPaths:[self.collectionView indexPathsForVisibleItems]];

    quindi:

    [self.collectionView reloadData];
    • Che linea ha causato la mia app crash – “*** errore di Asserzione in[UICollectionView _endItemAnimations], /SourceCache/UIKit_Sim/UIKit-2935.137/UICollectionView.m:3840”
    • Probabilmente l’esecuzione di altre animazioni allo stesso tempo.. prova a metterli in una performBatchUpdates:completion: blocco?
    • Questo ha funzionato per me, ma io non sono sicuro di capire il motivo per cui è necessario. Qualsiasi idea di cosa si tratta?
    • Purtroppo non ho idea.. credo che sia un qualche tipo di bug in iOS, non so se è stato risolto nelle versioni successive o meno anche se, come non ho testato a partire dal e il progetto che ho avuto il problema non è non è più un problema mio 🙂
    • Bene, sono contento di sentire che non è un problema per voi più, almeno! Vorrei aggiungere a questo che ho avuto alcuni problemi di crash con questo codice fino a quando ho invertito l’ordine delle chiamate (quindi reloadData prima e poi reloadItemsAtIndexPaths), ma dal momento che non so perché funziona a tutti io di certo non può spiegare il motivo che ha aiutato!
    • Per me funziona. Grazie!
    • Questo bug è solo pura stronzata ! Tutte le mie cellule sono state – a caso – di scomparire quando ho ricaricato il mio collectionView, solo se era un tipo specifico di cellule nella mia collezione. Ho perso due giorni perché non riuscivo a capire cosa stava succedendo, e ora che ho applicato la soluzione e che funziona, non riesco ancora a capire perché è ora di lavoro. Che frustrazione ! Comunque, grazie per l’aiuto 😀 !!
    • Non so perché, ma ho dovuto seguire questa risposta per ottenere celle visibili per allineare & dimensione correttamente sulla modifica della rotazione. Grazie!
    • la risposta dovrebbe funzionare per la maggior parte ed è meno prestazioni pesante
    • Non so perché, ma questa salvato la mia giornata. Grazie 🙂
    • Vi ringrazio molto. Risolvere il mio problema.
    • Nel mio caso, reloadItemsAtIndexPaths doveva essere chiamato dopo reloadData a causa di una modifica dei dati.

  3. 26

    Ho avuto esattamente lo stesso problema, comunque sono riuscito a trovare quello che stava succedendo sbagliato.
    Nel mio caso ho chiamato reloadData dal collectionView:cellForItemAtIndexPath: che sembra non essere corretto.

    Invio chiamata di reloadData per la coda principale è stato risolto il problema una volta e per sempre.

      dispatch_async(dispatch_get_main_queue(), ^{
        [self.collectionView reloadData];
      });
    • u può dirmi che cosa questa linea è per [self.collectionData.collectionViewLayout invalidateLayout];
    • Non dovrebbe essere lì. Grazie per la segnalazione.
    • Questo risolto anche per me, nel mio caso reloadData di essere chiamata da un cambiamento di osservatore.
    • bel lavoro. Questo ha risolto il mio problema. Grazie mille
    • Anche questo vale per collectionView(_:willDisplayCell:forItemAtIndexPath:)
  4. 19

    Ricaricare alcuni elementi non ha funzionato per me. Nel mio caso, e solo perché il collectionView sto usando è solo una parte, ho semplicemente ricaricare la particolare sezione.
    Questa volta il contenuto correttamente ricaricata.
    Strano che questo succede su iOS 7 (7.0.3)

    [self.collectionView reloadSections:[NSIndexSet indexSetWithIndex:0]];
  5. 12

    Swift 5 – 4 – 3

    //GCD    
    DispatchQueue.main.async(execute: collectionView.reloadData)
    
    //Operation
    OperationQueue.main.addOperation(collectionView.reloadData)

    Swift 2

    //Operation
    NSOperationQueue.mainQueue().addOperationWithBlock(collectionView.reloadData)
  6. 11

    Ho avuto lo stesso problema con reloadData su iOS 7. Dopo una lunga sessione di debug, ho trovato il problema.

    Su iOS7, reloadData su UICollectionView non annulla i precedenti aggiornamenti che non hanno ancora terminato (Aggiornamenti che viene chiamato all’interno di performBatchUpdates: blocco).

    La soluzione migliore per risolvere questo problema, è l’arresto di tutti gli aggiornamenti che attualmente trattati e chiamare reloadData. Non riesco a trovare un modo per annullare o interrompere un blocco di performBatchUpdates. Pertanto, per risolvere il bug, ho salvato un flag che indica se c’è un performBatchUpdates blocco attualmente in fase di elaborazione. Se non c’è un aggiornamento del blocco attualmente in fase di elaborazione, posso chiamare reloadData immediatamente e tutto funziona come previsto. Se c’è un aggiornamento di blocco attualmente in fase di elaborazione, chiamerò reloadData il blocco completo di performBatchUpdates.

    • Dove è l’esecuzione di tutte le modifiche all’interno performBatchUpdate? Alcuni in alcuni? Tutti fuori? Post molto interessante.
    • Io sto usando la visualizzazione di raccolta con NSFetchedResultsController per visualizzare i dati CoreData. Quando il NSFetchedResultsController delegato notificare le modifiche, mi raccogliere tutti gli aggiornamenti e li chiamano all’interno performBatchUpdates. Quando il NSFetchedResultsController richiesta predicato è cambiato, reloadData deve essere chiamato.
  7. 4

    Anche io ho avuto questo problema. Per coincidenza, ho aggiunto un pulsante sulla parte superiore del collectionview per forza di ricarica per i test e tutto ad un tratto i metodi iniziato a ricevere chiamate.

    Anche solo l’aggiunta di qualcosa di semplice come

    UIView *aView = [UIView new];
    [collectionView addSubView:aView];

    potrebbe causare i metodi di essere chiamato

    Anche io ho giocato un po ‘ con la dimensione del frame – e voilà i metodi sono stati sempre chiamato.

    Ci sono un sacco di bug con iOS7 UICollectionView.

    • Sono contento di vedere (in certian modi) che altri hanno riscontrato questo problema. Grazie per la soluzione.
  8. 3

    È possibile utilizzare questo metodo

    [collectionView reloadItemsAtIndexPaths:arayOfAllIndexPaths];

    È possibile aggiungere tutti indexPath di oggetti di UICollectionView in un array arrayOfAllIndexPaths da iterare il ciclo per tutte le sezioni e filari con utilizzo del metodo sotto

    [aray addObject:[NSIndexPath indexPathForItem:j inSection:i]];

    Spero che hai capito e può risolvere il tuo problema. Se avete bisogno di una spiegazione più dettagliata, si prega di rispondere.

  9. 3

    Soluzione data dal Shaunti Fondrisi è quasi perfetto. Ma ad un pezzo di codice o i codici di come enqueue l’esecuzione di UICollectionView‘s reloadData() per NSOperationQueue‘s mainQueue, infatti, mette l’intervallo di esecuzione per l’inizio del prossimo ciclo di eventi nel periodo di ciclo, che potrebbe fare il UICollectionView aggiornamento con un colpo di frusta.

    Per risolvere questo problema. Dobbiamo mettere l’intervallo di esecuzione di uno stesso pezzo di codice alla fine del corrente ciclo di eventi, ma non per l’inizio del prossimo. E si può raggiungere questo facendo uso di CFRunLoopObserver.

    CFRunLoopObserver osserva la sorgente di ingresso di attesa attività e l’esecuzione di un loop di ingresso e di uscita attività.

    public struct CFRunLoopActivity : OptionSetType {
        public init(rawValue: CFOptionFlags)
    
        public static var Entry: CFRunLoopActivity { get }
        public static var BeforeTimers: CFRunLoopActivity { get }
        public static var BeforeSources: CFRunLoopActivity { get }
        public static var BeforeWaiting: CFRunLoopActivity { get }
        public static var AfterWaiting: CFRunLoopActivity { get }
        public static var Exit: CFRunLoopActivity { get }
        public static var AllActivities: CFRunLoopActivity { get }
    }

    Tra tali attività, .AfterWaiting può essere osservata durante l’attuale ciclo di eventi sta per finire, e .BeforeWaiting può essere osservata quando il prossimo ciclo di eventi ha appena iniziato.

    C’è solo un NSRunLoop istanza per NSThread e NSRunLoop esattamente unità il NSThread, si può considerare che gli accessi provengono dalla stessa NSRunLoop istanza di sempre non superano mai i thread.

    In base ai punti citati prima, possiamo ora scrivere il codice: un NSRunLoop compito dispatcher:

    import Foundation
    import ObjectiveC
    
    public struct Weak<T: AnyObject>: Hashable {
        private weak var _value: T?
        public weak var value: T? { return _value }
        public init(_ aValue: T) { _value = aValue }
    
        public var hashValue: Int {
            guard let value = self.value else { return 0 }
            return ObjectIdentifier(value).hashValue
        }
    }
    
    public func ==<T: AnyObject where T: Equatable>(lhs: Weak<T>, rhs: Weak<T>)
        -> Bool
    {
        return lhs.value == rhs.value
    }
    
    public func ==<T: AnyObject>(lhs: Weak<T>, rhs: Weak<T>) -> Bool {
        return lhs.value === rhs.value
    }
    
    public func ===<T: AnyObject>(lhs: Weak<T>, rhs: Weak<T>) -> Bool {
        return lhs.value === rhs.value
    }
    
    private var dispatchObserverKey =
    "com.WeZZard.Nest.NSRunLoop.TaskDispatcher.DispatchObserver"
    
    private var taskQueueKey =
    "com.WeZZard.Nest.NSRunLoop.TaskDispatcher.TaskQueue"
    
    private var taskAmendQueueKey =
    "com.WeZZard.Nest.NSRunLoop.TaskDispatcher.TaskAmendQueue"
    
    private typealias DeallocFunctionPointer =
        @convention(c) (Unmanaged<NSRunLoop>, Selector) -> Void
    
    private var original_dealloc_imp: IMP?
    
    private let swizzled_dealloc_imp: DeallocFunctionPointer = {
        (aSelf: Unmanaged<NSRunLoop>,
        aSelector: Selector)
        -> Void in
    
        let unretainedSelf = aSelf.takeUnretainedValue()
    
        if unretainedSelf.isDispatchObserverLoaded {
            let observer = unretainedSelf.dispatchObserver
            CFRunLoopObserverInvalidate(observer)
        }
    
        if let original_dealloc_imp = original_dealloc_imp {
            let originalDealloc = unsafeBitCast(original_dealloc_imp,
                DeallocFunctionPointer.self)
            originalDealloc(aSelf, aSelector)
        } else {
            fatalError("The original implementation of dealloc for NSRunLoop cannot be found!")
        }
    }
    
    public enum NSRunLoopTaskInvokeTiming: Int {
        case NextLoopBegan
        case CurrentLoopEnded
        case Idle
    }
    
    extension NSRunLoop {
    
        public func perform(closure: ()->Void) -> Task {
            objc_sync_enter(self)
            loadDispatchObserverIfNeeded()
            let task = Task(self, closure)
            taskQueue.append(task)
            objc_sync_exit(self)
            return task
        }
    
        public override class func initialize() {
            super.initialize()
    
            struct Static {
                static var token: dispatch_once_t = 0
            }
            //make sure this isn't a subclass
            if self !== NSRunLoop.self {
                return
            }
    
            dispatch_once(&Static.token) {
                let selectorDealloc: Selector = "dealloc"
                original_dealloc_imp =
                    class_getMethodImplementation(self, selectorDealloc)
    
                let swizzled_dealloc = unsafeBitCast(swizzled_dealloc_imp, IMP.self)
    
                class_replaceMethod(self, selectorDealloc, swizzled_dealloc, "@:")
            }
        }
    
        public final class Task {
            private let weakRunLoop: Weak<NSRunLoop>
    
            private var _invokeTiming: NSRunLoopTaskInvokeTiming
            private var invokeTiming: NSRunLoopTaskInvokeTiming {
                var theInvokeTiming: NSRunLoopTaskInvokeTiming = .NextLoopBegan
                guard let amendQueue = weakRunLoop.value?.taskAmendQueue else {
                    fatalError("Accessing a dealloced run loop")
                }
                dispatch_sync(amendQueue) { () -> Void in
                    theInvokeTiming = self._invokeTiming
                }
                return theInvokeTiming
            }
    
            private var _modes: NSRunLoopMode
            private var modes: NSRunLoopMode {
                var theModes: NSRunLoopMode = []
                guard let amendQueue = weakRunLoop.value?.taskAmendQueue else {
                    fatalError("Accessing a dealloced run loop")
                }
                dispatch_sync(amendQueue) { () -> Void in
                    theModes = self._modes
                }
                return theModes
            }
    
            private let closure: () -> Void
    
            private init(_ runLoop: NSRunLoop, _ aClosure: () -> Void) {
                weakRunLoop = Weak<NSRunLoop>(runLoop)
                _invokeTiming = .NextLoopBegan
                _modes = .defaultMode
                closure = aClosure
            }
    
            public func forModes(modes: NSRunLoopMode) -> Task {
                if let amendQueue = weakRunLoop.value?.taskAmendQueue {
                    dispatch_async(amendQueue) { [weak self] () -> Void in
                        self?._modes = modes
                    }
                }
                return self
            }
    
            public func when(invokeTiming: NSRunLoopTaskInvokeTiming) -> Task {
                if let amendQueue = weakRunLoop.value?.taskAmendQueue {
                    dispatch_async(amendQueue) { [weak self] () -> Void in
                        self?._invokeTiming = invokeTiming
                    }
                }
                return self
            }
        }
    
        private var isDispatchObserverLoaded: Bool {
            return objc_getAssociatedObject(self, &dispatchObserverKey) !== nil
        }
    
        private func loadDispatchObserverIfNeeded() {
            if !isDispatchObserverLoaded {
                let invokeTimings: [NSRunLoopTaskInvokeTiming] =
                [.CurrentLoopEnded, .NextLoopBegan, .Idle]
    
                let activities =
                CFRunLoopActivity(invokeTimings.map{ CFRunLoopActivity($0) })
    
                let observer = CFRunLoopObserverCreateWithHandler(
                    kCFAllocatorDefault,
                    activities.rawValue,
                    true, 0,
                    handleRunLoopActivityWithObserver)
    
                CFRunLoopAddObserver(getCFRunLoop(),
                    observer,
                    kCFRunLoopCommonModes)
    
                let wrappedObserver = NSAssociated<CFRunLoopObserver>(observer)
    
                objc_setAssociatedObject(self,
                    &dispatchObserverKey,
                    wrappedObserver,
                    .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            }
        }
    
        private var dispatchObserver: CFRunLoopObserver {
            loadDispatchObserverIfNeeded()
            return (objc_getAssociatedObject(self, &dispatchObserverKey)
                as! NSAssociated<CFRunLoopObserver>)
                .value
        }
    
        private var taskQueue: [Task] {
            get {
                if let taskQueue = objc_getAssociatedObject(self,
                    &taskQueueKey)
                    as? [Task]
                {
                    return taskQueue
                } else {
                    let initialValue = [Task]()
    
                    objc_setAssociatedObject(self,
                        &taskQueueKey,
                        initialValue,
                        .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    
                    return initialValue
                }
            }
            set {
                objc_setAssociatedObject(self,
                    &taskQueueKey,
                    newValue,
                    .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    
            }
        }
    
        private var taskAmendQueue: dispatch_queue_t {
            if let taskQueue = objc_getAssociatedObject(self,
                &taskAmendQueueKey)
                as? dispatch_queue_t
            {
                return taskQueue
            } else {
                let initialValue =
                dispatch_queue_create(
                    "com.WeZZard.Nest.NSRunLoop.TaskDispatcher.TaskAmendQueue",
                    DISPATCH_QUEUE_SERIAL)
    
                objc_setAssociatedObject(self,
                    &taskAmendQueueKey,
                    initialValue,
                    .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
    
                return initialValue
            }
        }
    
        private func handleRunLoopActivityWithObserver(observer: CFRunLoopObserver!,
            activity: CFRunLoopActivity)
            -> Void
        {
            var removedIndices = [Int]()
    
            let runLoopMode: NSRunLoopMode = currentRunLoopMode
    
            for (index, eachTask) in taskQueue.enumerate() {
                let expectedRunLoopModes = eachTask.modes
                let expectedRunLoopActivitiy =
                CFRunLoopActivity(eachTask.invokeTiming)
    
                let runLoopModesMatches = expectedRunLoopModes.contains(runLoopMode)
                    || expectedRunLoopModes.contains(.commonModes)
    
                let runLoopActivityMatches =
                activity.contains(expectedRunLoopActivitiy)
    
                if runLoopModesMatches && runLoopActivityMatches {
                    eachTask.closure()
                    removedIndices.append(index)
                }
            }
    
            taskQueue.removeIndicesInPlace(removedIndices)
        }
    }
    
    extension CFRunLoopActivity {
        private init(_ invokeTiming: NSRunLoopTaskInvokeTiming) {
            switch invokeTiming {
            case .NextLoopBegan:        self = .AfterWaiting
            case .CurrentLoopEnded:     self = .BeforeWaiting
            case .Idle:                 self = .Exit
            }
        }
    }

    Con il codice di prima, ora siamo in grado di inviare l’esecuzione di UICollectionView‘s reloadData() per la fine del corrente ciclo di eventi da questo pezzo di codice:

    NSRunLoop.currentRunLoop().perform({ () -> Void in
         collectionView.reloadData()
        }).when(.CurrentLoopEnded)

    Infatti, ad un NSRunLoop compito dispatcher è già stato in uno dei miei personali utilizzati quadro: Nido. E qui è il suo repository su GitHub: https://github.com/WeZZard/Nest

  10. 1

    Grazie prima di tutto per questo thread, molto utile. Ho avuto un problema simile con Ricarica Dati tranne il sintomo era che le cellule specifiche, non poteva più essere selezionato in modo permanente, mentre altri potrebbero. Nessuna chiamata per indexPathsForSelectedItems metodo o equivalente. Debug sottolineato per Ricaricare i Dati. Ho provato entrambe le opzioni di cui sopra ; e finì per adottare il ReloadItemsAtIndexPaths opzione come le altre opzioni non funzionano nel mio caso o in vista raccolta di flash per un milli-secondo. Il codice riportato di seguito funziona bene:

    NSMutableArray *indexPaths = [[NSMutableArray alloc] init]; 
    NSIndexPath *indexPath;
    for (int i = 0; i < [self.assets count]; i++) {
             indexPath = [NSIndexPath indexPathForItem:i inSection:0];
             [indexPaths addObject:indexPath];
    }
    [collectionView reloadItemsAtIndexPaths:indexPaths];`
  11. 0

    È successo con me in iOS 8.1 sdk, ma ho corretto quando ho notato che anche dopo l’aggiornamento del datasource il metodo numberOfItemsInSection: non era di ritorno il nuovo conteggio di elementi. Ho aggiornato il conteggio e capito di lavoro.

    • come hai fatto l’aggiornamento che contano per favore.. Tutti i metodi di cui sopra non sono riusciti a lavorare per me in swift 3.
  12. 0

    Si fa a impostare UICollectionView.contentInset? rimuovere sinistra e a destra edgeInset, tutto è ok dopo che ho rimuoverli, il bug esiste ancora in iOS8.3 .

  13. 0

    Di controllare che ogni uno dei UICollectionView Delegato metodi fa quello che ci si aspetta di fare. Per esempio, se

    collectionView:layout:sizeForItemAtIndexPath:

    non restituisce una dimensione valida, il sistema di ricarica non funziona…

  14. 0

    provare questo codice.

     NSArray * visibleIdx = [self.collectionView indexPathsForVisibleItems];
    
        if (visibleIdx.count) {
            [self.collectionView reloadItemsAtIndexPaths:visibleIdx];
        }
  15. 0
     dispatch_async(dispatch_get_main_queue(), ^{
    
                [collectionView reloadData];
                [collectionView layoutIfNeeded];
                [collectionView reloadData];
    
    
            });

    ha funzionato per me.

  16. 0

    Ecco come ha funzionato per me in Swift 4

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    
    let cell = campaignsCollection.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! Cell
    
    cell.updateCell()
    
        //TO UPDATE CELLVIEWS ACCORDINGLY WHEN DATA CHANGES
        DispatchQueue.main.async {
            self.campaignsCollection.reloadData()
        }
    
        return cell
    }
  17. -1
    inservif (isInsertHead) {
       [self insertItemsAtIndexPaths:tmpPoolIndex];
       NSArray * visibleIdx = [self indexPathsForVisibleItems];
       if (visibleIdx.count) {
           [self reloadItemsAtIndexPaths:visibleIdx];
       }
    }else if (isFirstSyncData) {
        [self reloadData];
    }else{
       [self insertItemsAtIndexPaths:tmpPoolIndex];
    }

Lascia un commento