The collection view will very likely have corresponding ivars for the animation block and its completion handler. If that's the case, it should (shall) create a copy of the anonymous animation (updates) and completion block when receiving them in `performBatchUpdate:completion:`.
Now, `finish` is an "imported field" of the anonymous completion handler. The copy operation of the anonymous completion handler will cause the block `finish` to be copied as well. Since the outer block lives on the heap, the imported fields of `finish` will live there, too. Effectively, imported fields will be "copied" into the storage area of the outermost block. It seems to me, that block `finish` should have a ref count of +1 within the anonymous completion handler. Vlad, could you please verify your observations and possibly create a simple test class mimicking the behavior of the collection view (no animation, just a dummy async method), e.g. dispatch_block_t completion = ^{ NSLog(@"invoking completion"); }; dispatch_block_t updates = ^{ NSLog(@"invoking updates"); }; dispatch_block_t finish = ^{ NSLog(@"invoking finish"); if (completion) { completion(); } }; if (animated) { self.testClass performDummyMethod:^{ updates(); } completion:^(BOOL finished) { finish(); }]; When TestClass actually makes copies of the block when setting its ivars `_updates` and `_completion`, it should work (IMO). See also: "Block Implementation Specification" <http://clang.llvm.org/docs/Block-ABI-Apple.html> (especially, "Imported const copy of Block reference). Andreas On 09.08.2013, at 16:57, Vlad Alekseev <ippo...@me.com> wrote: > Hey! > > I have a method where I update my collection view's layout parameter and want > to have a completion block invoked when animation completes: > > - (void)transitionAnimated:(BOOL)animated > completion:(dispatch_block_t)completion > { > dispatch_block_t updates = ^{ > self.layout.maximumScale = self.maximumScale; > }; > > dispatch_block_t finish = ^{ > if (completion) { > completion(); > } > }; > > if (animated) { > self.collectionView.userInteractionEnabled = NO; > [self.collectionView performBatchUpdates:^{ > updates(); > } completion:^(BOOL finished) { > self.collectionView.userInteractionEnabled = YES; > finish(); > }]; > } > else { > updates(); > [self.layout invalidateLayout]; > finish(); > } > } > > It works as expected if collection view contains some items. But it crashes > if collection view is empty. And it crashes here: > > } completion:^(BOOL finished) { > self.collectionView.userInteractionEnabled = YES; > finish(); // ---- CRASH because finish == NULL > }]; > > Debugger says that finish is nil: > > (lldb) p finish > (dispatch_block_t) $1 = <parent is NULL> > > What is going on with that block? Any ideas why it gets NULL-ified? > _______________________________________________ > > Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) > > Please do not post admin requests or moderator comments to the list. > Contact the moderators at cocoa-dev-admins(at)lists.apple.com > > Help/Unsubscribe/Update your Subscription: > https://lists.apple.com/mailman/options/cocoa-dev/agrosam%40onlinehome.de > > This email sent to agro...@onlinehome.de _______________________________________________ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com