ios objective-c uikit uicollectionview exc-bad-access
https://github.com/lequysang/gitfiles02/blob/master/CollectionViewWithDecorationView.zip

ios - Acceso incorrecto en



objective-c uikit (4)

¿Puede intentar lo siguiente? Desplácese por la vista principal de uicollection para que el encabezado no se muestre ... (aún mejor) y luego en el simulador, intente realizar una advertencia de memoria ... usando Hardware-> Simular memoria de advertencia ...

Esto probablemente debería crear un reciclaje y eliminación de celdas (la vista uicollection debería destruir todo lo que no es importante en este momento ... si esto sucede, el encabezado se desasignará y aún tendrá una referencia débil a él ... así que cualquier cosa que haga sucederá debido a un acceso incorrecto ... también es "imposible" reproducirlo en el simulador debido a la falta de advertencia de memoria (solo las creadas de forma explícita) ...

La vista parece pesada, ¿puedes intentar hacer esto y publicar los resultados?

Estoy teniendo un accidente extraño en mi UICollectionView. El UICollectionView se bloquea en una celda UICollectionView de otro UICollectionView.

No puedo reproducir el problema, parece suceder a veces si el UICollectionView interno se inicializa nuevamente porque el CollectionView externo está recargando sus celdas.

com.apple.main-thread Crashed 0 libobjc.A.dylib objc_msgSend + 9 1 UIKit -[UICollectionViewData _setLayoutAttributes:atGlobalItemIndex:] + 60 2 UIKit __45-[UICollectionViewData validateLayoutInRect:]_block_invoke_0 + 668 3 UIKit -[UICollectionViewData validateLayoutInRect:] + 1408 4 UIKit -[UICollectionViewData layoutAttributesForElementsInRect:] + 82 5 UIKit -[UICollectionView setCollectionViewLayout:animated:] + 1644 6 MyApp BSCTopnewsCollectionView.m line 52 -[BSCTopnewsCollectionView setupBSCTopnewsCollectionView] 7 MyApp BSCTopnewsCollectionView.m line 27 -[BSCTopnewsCollectionView setWeakDelegatePointer:] 8 Myapp BSCFrontPageViewController.m line 550 -[BSCFrontPageViewController collectionView:cellForItemAtIndexPath:] 9 UIKit -[UICollectionView _createPreparedCellForItemAtIndexPath:withLayoutAttributes:] + 252 10 UIKit -[UICollectionView _updateVisibleCellsNow:] + 2672 11 UIKit -[UICollectionView layoutSubviews] + 214 12 UIKit -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 258 13 QuartzCore -[CALayer layoutSublayers] + 214 14 QuartzCore CA::Layer::layout_if_needed(CA::Transaction*) + 460 15 QuartzCore CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 16 16 QuartzCore CA::Context::commit_transaction(CA::Transaction*) + 238 17 QuartzCore CA::Transaction::commit() + 316 18 QuartzCore CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) + 60 19 CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 20 25 UIKit UIApplicationMain + 1120 26 MyApp main.m line 16 main Exception Type: EXC_BAD_ACCESS Code: KERN_INVALID_ADDRESS at 0x158848

Lo que estoy haciendo en la línea 52 en setupBSCTopnewsCollectionView es

BSCInfiniteLayout *infiniteLayout = [[BSCInfiniteLayout alloc] init]; (line 52) self.collectionView.collectionViewLayout = infiniteLayout; Edición: - [BSCFrontPageViewController collectionView: cellForItemAtIndexPath:]

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { if([collectionView isEqual:self.collectionView]) { if(indexPath.row == 0) // Header Cell { BSCTopnewsCollectionView *cell = [collectionView dequeueReusableCellWithReuseIdentifier:BSCHeaderReuseIdentifier forIndexPath:indexPath]; cell.dataSource = self; cell.weakDelegatePointer = self; self.topNewsCollectionView = cell; return cell; } else { //create normal cells } } else if ([collectionView isEqual:self.topNewsCollectionView.collectionView]) { BSCTopNewsHeaderCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:BSCTopNewsCellReuseIdentifier forIndexPath:indexPath]; BSCNews *topnews = [self.topNews objectAtIndex:indexPath.row]; [cell setEntity:topnews]; return cell; } }

Algunas aclaraciones para el método llama allí:

- (void)setWeakDelegatePointer:(BSCFrontPageViewController *)weakDelegatePointer { _weakDelegatePointer = weakDelegatePointer; [self setupBSCTopnewsCollectionView]; [self.collectionView reloadData]; } - (void)setupBSCTopnewsCollectionView { self.collectionView.delegate = self.weakDelegatePointer; self.collectionView.dataSource = self.weakDelegatePointer; BSCInfiniteLayout *infiniteLayout = [[BSCInfiniteLayout alloc] init]; infiniteLayout.delegate = self; // Setup Layout self.collectionView.collectionViewLayout = infiniteLayout; self.collectionView.showsHorizontalScrollIndicator = NO; self.collectionView.pagingEnabled = YES; // Register Cells [self.collectionView registerNib:[UINib nibWithNibName:@"BSCTopNewsHeaderCell" bundle:nil] forCellWithReuseIdentifier:BSCTopNewsCellReuseIdentifier]; } Edit3 : El accidente solo parece ocurrir en ocasiones especiales. Si la aplicación estaba en segundo plano, pero todavía en la memoria y el usuario la abre de nuevo. Luego revisa nuestra API en busca de nuevos datos, y si encuentra algo, los cargará y recargará toda la colección externa View. Eso es cuando se produce el accidente.

Si se recarga CollectionView mientras la aplicación se ejecuta sin estar en segundo plano, al principio todo está bien.

Para hacer la configuración un poco más clara.

Parece que su vista de delegado o colección interna está muerta (¿qué hace setWeakDelegatePointer: do?). Prueba el instrumento Zombies en el simulador, debería marcar si los zombies son el caso. También establezca el "punto de interrupción de las excepciones" para todas las excepciones en xCode (ayudará a su depuración cuando la aplicación se ejecuta desde xCode y no desde instrumentos). También verifique su -[BSCFrontPageViewController collectionView:cellForItemAtIndexPath:] , puede que esté liberando esa vista de colección interna al reutilizarla.

Edición: ¿Por qué no solo agregar la celda del encabezado como encabezado y no la celda 0 (ejemplo de encabezado en la vista de colección here )? También revise (solo para asegurarse de que no sea una razón de la falla) sus identificadores de reutilización cuando esté creando celdas normales para la vista de la colección externa. También envíe avisos de mem periódicamente al depurar en el simulador.

Además, ¿por qué usar otra vista de colección para el encabezado? Puedes usar algo similar a iCarousel para tal diseño.


Primero, arrastre y suelte un UICollectionView a su ViewController en XIB, conecte Delegate, fuente de datos a ViewController (esto es solo ViewController principal)

No use 2 celdas de plumilla diferentes para 1 CollectionView, porque solo puede registrar 1 plumilla. Mejor uso DecorationView como HeaderView. Crear nueva clase HeaderView: UICollectionReusableView. Este UICollectionReusableView es una subclase de UIView que se puede reutilizar dentro de UICollectionView junto con UICollectionViewCell. Ahora puedes registrar ambos tipos:

[self.collectionView registerNib:[UINib nibWithNibName:@"MyCell" bundle:nil] forCellWithReuseIdentifier:@"CELL"]; [self.collectionView registerNib:[UINib nibWithNibName:@"HeaderView" bundle:nil] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"HeaderCell"];

A continuación, arrastre otro UICollectionView a este HeaderView, conéctese con IBOutlet dentro de HeaderView.h. Aquí, es mejor establecer Delegate, DataSource en esta clase para el control. También registra qué Nib Cell utilizará este CollectionView. Hazlo en awakeFromNib porque registrasNib antes

- (void)awakeFromNib{ [self.topCollectionView registerNib:[UINib nibWithNibName:@"TopCell" bundle:nil] forCellWithReuseIdentifier:@"TopCell"]; [self.topCollectionView setDataSource:self]; [self.topCollectionView setDelegate:self]; }

Funcionará bien, si almacena su fuente de datos afuera, solo haga otra propiedad y asigne, luego use para regresar dentro de la fuente de datos aquí.

Si desea saber cuándo debe hacer clic en Cell dentro de headerView, use un protocolo customDelegate para enviar delegados a ViewController cuando haga clic en HeaderCell.

Este es mi código, espero que lo entiendas y puedas aplicar tus datos aquí:

https://github.com/lequysang/gitfiles02/blob/master/CollectionViewWithDecorationView.zip


Sacando nuestra "Respuesta" de los comentarios.

Lamentablemente ninguna de las respuestas ayudó. Terminé refactorizando todo el asunto y luego el problema desapareció. Incluso tuve una charla bastante detallada con un ingeniero de DTS de Apple que tampoco sabía qué hacer. Así que acabamos de refaccionar. Lo siento :/