2014-12-04 20 views
8

Sto scrivendo un'app iOS8 utilizzando il framework Photos. Mi piace moltissimo PHFetchResultChangeDetails. Ma c'è qualcosa che non capisco: quando salvi nuove foto sul rullino fotografico usando il seguente codice, poi torno indietro inserimenti e modifiche. Mi aspetto solo inserimenti.Perché i miei PHFetchResultChangeDetails hanno cambiatoIndexes, quando tutto ciò che ho fatto è stato inserito alla fine?

Per rendere più concreto:

[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ 

PHAssetChangeRequest* newPhotoChangeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image]; 
PHAssetCollectionChangeRequest* albumChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:_album]; 
[albumChangeRequest addAssets:[NSArray arrayWithObject:newPhotoChangeRequest.placeholderForCreatedAsset]]; 
... 

L'operazione è quello di inserire 3 foto utilizzando il codice di cui sopra. Prima: 5 foto su ipad. Dopo: 8 foto in ipad. punto di interruzione sul gestore PHFetResultChangeDetails mostra:

(lldb) po insertionIndexPaths 
<__NSArrayM 0x7913be10>(
<NSIndexPath: 0x78e39020> {length = 2, path = 0 - 5}, 
<NSIndexPath: 0x78e3c910> {length = 2, path = 0 - 6}, 
<NSIndexPath: 0x78e39480> {length = 2, path = 0 - 7} 
) 

-> BUONA: ha un senso! queste sono le foto che ho appena inserito (gli ultimi 3 indexpath).

(lldb) po changeIndexPaths 
<__NSArrayM 0x78e3c420>(
<NSIndexPath: 0x78e3c7e0> {length = 2, path = 0 - 2}, 
<NSIndexPath: 0x78e3c7a0> {length = 2, path = 0 - 3}, 
<NSIndexPath: 0x78e3c7b0> {length = 2, path = 0 - 4} 
) 

-> NON CAPIRE: perché questi sono considerati "modificati"? Queste sono le foto esistenti sul rullino fotografico ... Non ho fatto niente per loro.

Grazie per il vostro aiuto.

AGGIORNAMENTO: sembra che potrebbe avere qualcosa a che fare con la selezione. Ho dimenticato di menzionare che ciò accade quando ci sono già alcune celle selezionate. Quello che sto vedendo è che quando nuovi elementi vengono inseriti alla fine del collectionView, quindi, alcune celle selezionate vengono selezionate in modo casuale - penso che quelle che hanno cambiatoIndexPaths. Wow, questo fa schifo - non riesco a vedere come può farlo il mio codice! Qualche suggerimento?

UPDATE2: così, sembra che il cambiamento spuriIndexPath sia sempre il 3 indexPath direttamente prima dei percorsi di inserimento (che sono sempre alla fine). Perché?!

Update3: Sto anche vedendo crash in performBatchUpdates di UICollectionView, quando l'origine dati è correttamente up-to-date in anticipo, se ci sono entrambi gli inserti e le ricariche. Per esempio, quando il cambiamento è simile al seguente:

<PHFetchResultChangeDetails: 0x1742b91a0> 
before=<PHFetchResult: 0x1702b5d20> count=31, 
after=<PHFetchResult: 0x1702b5ea0> count=33, 
hasIncremental=1 deleted=(null), 
inserted=<NSMutableIndexSet: 0x17444aef0>[number of indexes: 2 (in 2 ranges), indexes: (30 32)], 
changed=<NSMutableIndexSet: 0x17444a9b0>[number of indexes: 4 (in 2 ranges), indexes: (27-29 31)], 
hasMoves=0 

... quindi il mio app crash in performBatchUpdates ad eccezione:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to delete item 31 from section 0 which only contains 31 items before the update' 

Ecco il codice di performBatchUpdates, che ho copiato direttamente dalla documentazione di Apple (!), quindi non vedo alcun motivo per cui changeIndexPaths contiene indice di 31, dato che prima gli inserti, il conteggio = 31:

[self.collectionView performBatchUpdates:^{ 

     if(deletionIndexPaths.count) 
       [self.collectionView deleteItemsAtIndexPaths:deletionIndexPaths]; 
     if(insertionIndexPaths.count) 
       [self.collectionView insertItemsAtIndexPaths:insertionIndexPaths]; 
     if(changeIndexPaths.count) 
       [self.collectionView reloadItemsAtIndexPaths:changeIndexPaths]; 
     if(moveBlock) 
       moveBlock(self.collectionView); 
} ... 
+1

Uffa stesso qui. Ho inserito 3 oggetti. Non ho selezioni, ma dovrei semplicemente inserirle e sta dicendo: modifica libreria foto possen

+0

Ho scoperto il mio problema, stavo chiamando fetchResultAfterChanges, due volte per la stessa modifica, una volta nel mio performChanges e poi ancora in un callback block. Ciò ha fatto sì che PHFetchResults non mostrasse le differenze che mi aspettavo e facesse esplodere la collectionView con aggiornamenti impropri. Ancora una volta, potrei non avere la stessa situazione, il mio codice non si occupa attualmente della selezione, ma lo sarà presto. – possen

risposta

3

Re: Update 3

Nonostante ciò che dice il codice di esempio, changedIndexes non può essere utilizzato in PerformBatchUpdate come questo.

gli indici PHFetchResultChangeDetails.changedIndexes sono relative all'originale risultati dopo vengono rimossi gli indici in removedIndexes, e dopo sono aggiunti i nuovi indici in insertedIndexes recupero.

Le API UITableView e UICollectionView richiedono tuttavia che i metodi reloadItems *, quando richiamati in un aggiornamento batch, abbiano indici da prima di eventuali altre modifiche.

Per fissare questa chiamata la ricarica e spostare le voci di fuori aggiornamenti batch, ad es .:

[self.collectionView performBatchUpdates:^{ 

     if(deletionIndexPaths.count) 
      [self.collectionView deleteItemsAtIndexPaths:deletionIndexPaths]; 
     if(insertionIndexPaths.count) 
      [self.collectionView insertItemsAtIndexPaths:insertionIndexPaths]; 
    } ... ] 
    if(changeIndexPaths.count) 
     [self.collectionView reloadItemsAtIndexPaths:changeIndexPaths]; 
    if(moveBlock) 
     moveBlock(self.collectionView); 
+0

Grazie! Qualche idea sul perché vengano generati cambiamenti spuriIndexPaths? Per ora non sto usando changeIndexPaths perché quelli casuali sembrano essere generati – xaphod