lukescott / DraggableCollectionView

Extension for the UICollectionView and UICollectionViewLayout that allows a user to move items with drag and drop. --- HELP WANTED --- Looking for maintainer and help with the experimental branch.
MIT License
549 stars 175 forks source link

Exception from layoutAttributesForItemAtIndexPath #18

Closed tonyarnold closed 11 years ago

tonyarnold commented 11 years ago

I have a collection view with 4 sections — everything except for the second section is static, and cannot be dragged.

I'm seeing an out of bounds exception when trying to drag any cell (on long press), which is bringing everything to a screeching halt.

What can I provide (short of the whole project) to help debug this?

lukescott commented 11 years ago

If you can reproduce with the Flow layout demo, that would help me debug it. Precise steps, referring to cell letter and number, of how it happened would help.

I would only need a video if it was something hard to reproduce.

tonyarnold commented 11 years ago

Luke, this might well be my use of NSFetchedResultsController to back this collection view. I'll try to repro anyway and get back to you with more details (or close the issue).

lukescott commented 11 years ago

Please let me know if you still have this issue.

bartoszhernas commented 9 years ago

Luke, I think you used function wrong way: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UICollectionViewLayout_class/index.html#//apple_ref/occ/instm/UICollectionViewLayout/layoutAttributesForItemAtIndexPath:

You use this method to provide layout information only for items that have a corresponding cell.

You are in LSCollectionViewHelper asking for cell with index that equals to number of items in collection view (so basically you are asking for not existing cell information:

    NSInteger items = [self.collectionView numberOfItemsInSection:i];
    NSIndexPath *nextIndexPath = [NSIndexPath indexPathForItem:items inSection:i];
    layoutAttr = [self.collectionView.collectionViewLayout layoutAttributesForItemAtIndexPath:nextIndexPath];

Maybe its crashing only with CoreData, its hard to tell and I cannot reproduce this issue in demo app

bartoszhernas commented 9 years ago

Stack:

(lldb) bt
* thread #1: tid = 0x14006c, 0x06432a6b libobjc.A.dylib`objc_exception_throw, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x06432a6b libobjc.A.dylib`objc_exception_throw
    frame #1: 0x0679aa93 CoreFoundation`-[__NSArrayM objectAtIndex:] + 243
    frame #2: 0x04520a67 UIKit`-[_UIFlowLayoutSection frameForItemAtIndexPath:] + 142
    frame #3: 0x044e5273 UIKit`-[UICollectionViewFlowLayout _frameForItem:inSection:usingData:] + 123
    frame #4: 0x044e0e07 UIKit`-[UICollectionViewFlowLayout layoutAttributesForItemAtIndexPath:usingData:] + 510
    frame #5: 0x044e1037 UIKit`-[UICollectionViewFlowLayout layoutAttributesForItemAtIndexPath:] + 339
  * frame #6: 0x00ab9b50 APP`-[LSCollectionViewHelper indexPathForItemClosestToPoint:](self=0x8190acd0, _cmd=0x010c04b5, point=CGPoint at 0xbff48840) + 2048 at LSCollectionViewHelper.m:191
    frame #7: 0x00aba1fe APP`-[LSCollectionViewHelper handleLongPressGesture:](self=0x8190acd0, _cmd=0x010c0435, sender=0x81e353a0) + 606 at LSCollectionViewHelper.m:224
    frame #8: 0x041db287 UIKit`_UIGestureRecognizerSendActions + 327
    frame #9: 0x041d9b04 UIKit`-[UIGestureRecognizer _updateGestureWithEvent:buttonEvent:] + 561
    frame #10: 0x041dbb4d UIKit`-[UIGestureRecognizer _delayedUpdateGesture] + 60
    frame #11: 0x041df4ca UIKit`___UIGestureRecognizerUpdate_block_invoke661 + 57
    frame #12: 0x041df38d UIKit`_UIGestureRecognizerRemoveObjectsFromArrayAndApplyBlocks + 317
    frame #13: 0x041d3296 UIKit`_UIGestureRecognizerUpdate + 3720
    frame #14: 0x067e79de CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30
    frame #15: 0x067e7920 CoreFoundation`__CFRunLoopDoObservers + 400
    frame #16: 0x067dd35a CoreFoundation`__CFRunLoopRun + 1226
    frame #17: 0x067dcbcb CoreFoundation`CFRunLoopRunSpecific + 443
    frame #18: 0x067dc9fb CoreFoundation`CFRunLoopRunInMode + 123
    frame #19: 0x07e5624f GraphicsServices`GSEventRunModal + 192
    frame #20: 0x07e5608c GraphicsServices`GSEventRun + 104
    frame #21: 0x03d9a8b6 UIKit`UIApplicationMain + 1526
    frame #22: 0x007e6145 APP`main(argc=3, argv=0xbff4a694) + 213 at main.m:16
    frame #23: 0x071d4ac9 libdyld.dylib`start + 1
(lldb) 
bartoszhernas commented 9 years ago

I found easy way to reproduce it on demo, it all happens when cellSize is not static

This added to ViewController in demo crashes:

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    [[sections objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
    return indexPath.row == 0 ?  CGSizeMake(200, 100) : CGSizeMake(100, 100);
}

But this is not:

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    [[sections objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
    return CGSizeMake(100, 100);
}

My guess is that internal implementation of FlowLayout is caching sizes for not static sizing. I will try to fix this issue tomorrow and will create pull request. Fix is needed only in two places and should not be hard.

lukescott commented 9 years ago

@bartg If you're talking about the master branch, different cell sizes don't work. The reason is how it is implemented. Best case the cell takes on the size of the old cell in the new position.

I do, however, have an incomplete experimental branch that supports differing cell sizes, but it's a bit ambitious as it requires re-implementing Apple's Flow layout. Since this was a hobby project for me and work has been crazy, I have not been able to dedicate enough time to it. I got as far as getting the drag logic working (you can move cells around), but the drop functionality still needs to be finished. Also things like cell margins may either be partially implemented or not at all. There are also some optimizations that Apple has made in iOS 7 / 8 in their Flow layout that my implementation does not have.

If you have the time I would really appreciate some help on the experimental branch. That branch should superseded anything on the master branch.

I'm also looking for a maintainer to go through the PR's and merge things that fix existing functionality of the existing implementation, flawed (IMO) as it may be.

bartoszhernas commented 9 years ago

I have just learned that its not possible. But even the current implementation its not working correctly with sections: if you add item to last line in section and new line should be created, the items animate below additional section)

Unfortunately in my case I have to use it at work and I checked LXReorderableCollectionViewFlowLayout solution and in this case it just works and I will switch to that one even thought I liked your idea of not changing data source.

bartoszhernas commented 9 years ago

I will make PR that fixes crash keeping the functionality in few minutes

bartoszhernas commented 9 years ago

https://github.com/lukescott/DraggableCollectionView/pull/51