UITableView beginUpdates / endUpdates에서 애니메이션이 종료되었음을 감지하는 방법은 무엇입니까?


116

insertRowsAtIndexPaths/deleteRowsAtIndexPaths랩핑을 사용하여 테이블 셀을 삽입 / 삭제 하고 beginUpdates/endUpdates있습니다. beginUpdates/endUpdatesrowHeight를 조정할 때도 사용하고 있습니다. 이러한 모든 작업은 기본적으로 애니메이션됩니다.

사용할 때 애니메이션이 종료되었음을 어떻게 알 수 beginUpdates/endUpdates있습니까?


1
참고 : 이것도 -scrollToRowAtIndexPath:atScrollPosition:animated:마찬가지입니다.
Ben Lachman 2014

답변:


292

이건 어때?

[CATransaction begin];

[CATransaction setCompletionBlock:^{
    // animation has finished
}];

[tableView beginUpdates];
// do some work
[tableView endUpdates];

[CATransaction commit];

이것은 tableView CALayer애니메이션이 내부적으로 애니메이션을 사용하기 때문에 작동합니다 . 즉, 열린 CATransaction. 개방 CATransaction이 존재 하지 않는 경우 (일반적인 경우) 암시 적으로 시작되고 현재 런 루프의 끝에서 종료됩니다. 하지만 여기에서했던 것처럼 직접 시작하면 저것을 사용합니다.


7
나를 위해 일하지 않았다. 애니메이션이 계속 실행되는 동안 완료 블록이 호출됩니다.
mrvincenzo 2013

2
@MrVincenzo 스 니펫에서 completionBlock이전 beginUpdatesendUpdates좋아요 를 설정 했습니까 ?
Rudolf Adamkovič

2
[CATransaction commit]이전이 아닌 후에 호출해야합니다 [tableView endUpdates].
Rudolf Adamkovič

6
셀에 애니메이션이있는 뷰 (예 : UIActivityIndicatorView)가 포함 된 경우 완료 블록이 호출되지 않습니다.
markturnip

3
이 모든 시간 동안 나는 이것을 결코 알지 못했습니다. 순금 !! tableView.reloadData ()의 필요한 악으로 멋진 애니메이션이 죽는 것을 보는 것보다 더 나쁜 것은 없습니다.
DogCoffee 2015 년

31

스위프트 버전


CATransaction.begin()

CATransaction.setCompletionBlock({
    do.something()
})

tableView.beginUpdates()
tableView.endUpdates()

CATransaction.commit()

6

iOS 11 이상을 타겟팅하는 경우 다음을 UITableView.performBatchUpdates(_:completion:)대신 사용해야 합니다.

tableView.performBatchUpdates({
    // delete some cells
    // insert some cells
}, completion: { finished in
    // animation complete
})

5

가능한 해결책은 UITableView가 추가되거나 제거 된 행과 일치하도록 콘텐츠 크기를 조정하기 때문에 를 호출 endUpdates하고 덮어 쓰는 UITableView에서 상속하는 것 setContentSizeMethod입니다. 이 접근 방식은 reloadData.

endUpdates호출 한 후에 만 ​​알림이 전송되도록하기 위해 endUpdates여기에 플래그를 덮어 쓰고 설정할 수도 있습니다.

// somewhere in header
@private BOOL endUpdatesWasCalled_;

-------------------

// in implementation file

- (void)endUpdates {
    [super endUpdates];
    endUpdatesWasCalled_ = YES;
}

- (void)setContentSize:(CGSize)contentSize {
    [super setContentSize:contentSize];

    if (endUpdatesWasCalled_) {
        [self notifyEndUpdatesFinished];
        endUpdatesWasCalled_ = NO;
    }
}

5

다음과 같이 UIView 애니메이션 블록에 작업을 포함 할 수 있습니다.

- (void)tableView:(UITableView *)tableView performOperation:(void(^)())operation completion:(void(^)(BOOL finished))completion
{
    [UIView animateWithDuration:0.0 animations:^{

        [tableView beginUpdates];
        if (operation)
            operation();
        [tableView endUpdates];

    } completion:^(BOOL finished) {

        if (completion)
            completion(finished);
    }];
}

https://stackoverflow.com/a/12905114/634940에 대한 크레딧 .


4
이 코드는 나를 위해 작동하지 않았습니다. 완료 블록은 endUpdates애니메이션이 완료되기 전에 호출 되었습니다.
Tim Camber

1
이것은 작동하지 않습니다. 이 샘플을 적용 할 때 tableview 애니메이션이 작동을 멈췄습니다.
Primoz990

지속 시간을 더 길게 만들어보십시오 (예 : 0.3 초)-효과가있을 것입니다 (저를 위해 일했습니다)
emem

1

아직 좋은 솔루션을 찾지 못했습니다 (UITableView 하위 클래스 화 부족). 나는 performSelector:withObject:afterDelay:지금 사용하기로 결정했습니다 . 이상적이지는 않지만 작업을 완료합니다.

업데이트 : scrollViewDidEndScrollingAnimation:이 목적으로 사용할 수있는 것 같습니다 (이것은 내 구현에 따라 다르며 주석을 참조하십시오).


1
scrollViewDidEndScrollingAnimation단지에 대한 응답이라고 setContentOffset하고scrollRectToVisible
samvermette

@samvermette 글쎄, 내 경우에는 beginUpdates / endUpdates가 호출 될 때 UITableView는 항상 애니메이션 스크롤을합니다. 그러나 이것은 내 구현에 따라 다르므로 최선의 답변은 아니지만 저에게 효과적이라는 데 동의합니다.
pixelfreak 2012-01-11

업데이트를 UIView 애니메이션 블록으로 묶을 수 있습니다. 내 대답은 stackoverflow.com/a/14305039/634940을 참조하십시오 .
Zdenek

0

다음 tableView:willDisplayCell:forRowAtIndexPath:과 같이 사용할 수 있습니다 .

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    NSLog(@"tableView willDisplay Cell");
    cell.backgroundColor = [UIColor colorWithWhite:((indexPath.row % 2) ? 0.25 : 0) alpha:0.70];
}

그러나 이미 테이블에있는 셀이 화면에서 화면으로 이동할 때도 호출되어 정확히 찾고있는 것이 아닐 수 있습니다. 방금 모든 UITableViewUIScrollView델리게이트 메서드를 살펴 봤는데 셀이 삽입 된 애니메이션 직후 처리 할 것이없는 것 같습니다.


애니메이션이 끝날 때 호출 할 메서드를 호출하면 안됩니다. endUpdates?

- (void)setDownloadedImage:(NSMutableDictionary *)d {
    NSIndexPath *indexPath = (NSIndexPath *)[d objectForKey:@"IndexPath"];
    [indexPathDelayed addObject:indexPath];
    if (!([table isDragging] || [table isDecelerating])) {
        [table beginUpdates];
        [table insertRowsAtIndexPaths:indexPathDelayed withRowAnimation:UITableViewRowAnimationFade];
        [table endUpdates];
        // --> Call Method Here <--
        loadingView.hidden = YES;
        [indexPathDelayed removeAllObjects];
    }
}

고마워, chown. 효과가 있다고 생각하지 마십시오 willDisplayCell. 모든 것이 해결 된 후에 만 ​​시각적 업데이트를해야하기 때문에 애니메이션 이후에 발생해야합니다.
pixelfreak 2011 년

np @pixelfreak,이 작업을 수행하는 다른 방법을 생각하면 알려 드리겠습니다.
chown하지
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.