Thời lượng hoạt ảnh hàng UITableView và gọi lại hoàn thành


98

Có cách nào để chỉ định thời lượng cho hoạt ảnh hàng UITableView hoặc nhận lệnh gọi lại khi hoạt ảnh hoàn tất không?

Những gì tôi muốn làm là nhấp nháy các chỉ báo cuộn sau khi hoạt ảnh hoàn tất. Làm flash trước sau đó không làm gì cả. Cho đến nay, cách giải quyết mà tôi có là trì hoãn nửa giây (đó dường như là thời lượng hoạt ảnh mặc định), tức là:

[self.tableView insertRowsAtIndexPaths:newRows
                      withRowAnimation:UITableViewRowAnimationFade];
[self.tableView performSelector:@selector(flashScrollIndicators)
                     withObject:nil
                     afterDelay:0.5];

Tôi đã không cố gắng bản thân mình, nhưng có lẽ điều này có thể làm điều đó, với một số xử lý đường chỉ số:- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath*)indexPath
Kalle

Câu trả lời:


3

Ngày nay, nếu bạn muốn làm điều này, có một chức năng mới bắt đầu từ iOS 11 :

- (void)performBatchUpdates:(void (^)(void))updates 
                 completion:(void (^)(BOOL finished))completion;

Trong các bản cập nhật đóng, bạn đặt mã tương tự như trong phần beginUpdates () / endUpdates. Và việc hoàn thành được thực hiện sau tất cả các hoạt ảnh.


Điều đó thật tuyệt. Tôi đã không nhận thấy sự bổ sung này.
Daniel Dickison

207

Chỉ cần xem qua điều này. Đây là cách thực hiện:

Objective-C

[CATransaction begin];
[tableView beginUpdates];
[CATransaction setCompletionBlock: ^{
    // Code to be executed upon completion
}];
[tableView insertRowsAtIndexPaths: indexPaths
                 withRowAnimation: UITableViewRowAnimationAutomatic];
[tableView endUpdates];
[CATransaction commit];

Nhanh

CATransaction.begin()
tableView.beginUpdates()
CATransaction.setCompletionBlock {
    // Code to be executed upon completion
}
tableView.insertRowsAtIndexPaths(indexArray, withRowAnimation: .Top)
tableView.endUpdates()
CATransaction.commit()

2
Một lần nữa, hoạt động hoàn hảo ở đây. iOS6 và tất cả. Đây là một cơ chế phù hợp được SDK hỗ trợ để ghi đè các thuộc tính trong hoạt ảnh mặc định. Có lẽ bạn có các hoạt ảnh bổ sung, chạy lâu hơn bên trong CATransaction của mình? Chúng được lồng vào nhau, bạn biết đấy.
karwag

1
Hoạt động tuyệt vời đối với tôi trong iOS6. Cảm ơn vì điều đó!
Aron

5
setAnimationDurationdường như không ảnh hưởng đến thời lượng chèn / xóa. iOS 6
Tom Redman

2
bất kỳ đề xuất nào về cách thay đổi thời lượng? CATransaction setAnimationDuration: dường như không tạo ra sự khác biệt.
Jeff Grimes

5
Hoạt động tốt đối với tôi trong iOS 5.1.1, 6.1, 7.0; Tuy nhiên, nếu bạn cần lấy một tableView.contentSize mới sau hoạt ảnh (như trường hợp của tôi), bạn phải sử dụng [self performanceSelectorOnMainThread: withObject: waitUntilDone:]; trong setCompletionBlock để gọi người đại diện của bạn trong lần chạy tiếp theo. nếu bạn gọi trực tiếp người đại diện của mình mà không có PerformSelectorOnMainThread, bạn sẽ nhận được giá trị cũ cho tableView.contentSize.
slamor

38

Mở rộng câu trả lời hay của karwag , hãy lưu ý rằng trên iOS 7, xung quanh CATransaction với UIView Animation cung cấp khả năng kiểm soát thời lượng hoạt ảnh bảng.

[UIView beginAnimations:@"myAnimationId" context:nil];

[UIView setAnimationDuration:10.0]; // Set duration here

[CATransaction begin];
[CATransaction setCompletionBlock:^{
    NSLog(@"Complete!");
}];

[myTable beginUpdates];
// my table changes
[myTable endUpdates];

[CATransaction commit];
[UIView commitAnimations];

Thời lượng của hoạt ảnh UIView không ảnh hưởng đến iOS 6. Có lẽ hoạt ảnh bảng iOS 7 được triển khai khác, ở cấp UIView.


Thời lượng hoạt ảnh dường như bị bỏ qua.
Dustin

26

Đó là một địa ngục của một thủ thuật hữu ích! Tôi đã viết một tiện ích mở rộng UITableView để tránh viết những thứ CATransaction mọi lúc.

import UIKit

extension UITableView {

    /// Perform a series of method calls that insert, delete, or select rows and sections of the table view.
    /// This is equivalent to a beginUpdates() / endUpdates() sequence, 
    /// with a completion closure when the animation is finished.
    /// Parameter update: the update operation to perform on the tableView.
    /// Parameter completion: the completion closure to be executed when the animation is completed.

    func performUpdate(_ update: ()->Void, completion: (()->Void)?) {

        CATransaction.begin()
        CATransaction.setCompletionBlock(completion)

        // Table View update on row / section
        beginUpdates()
        update()
        endUpdates()

        CATransaction.commit()
    }

}

Điều này được sử dụng như vậy:

// Insert in the tableView the section we just added in sections
self.tableView.performUpdate({
            self.tableView.insertSections([newSectionIndex], with: UITableViewRowAnimation.top)

        }, completion: {
            // Scroll to next section
            let nextSectionIndexPath = IndexPath(row: 0, section: newSectionIndex)
            self.tableView.scrollToRow(at: nextSectionIndexPath, at: .top, animated: true)
        })

Câu trả lời tuyệt vời! đây là một trong những lý do tôi yêu Swift
Gianni Carlo

@GianniCarlo, bạn cũng có thể làm điều này trong ObjC
CyberMew 22/03/18

@CyberMew có, nhưng việc tạo ra một loại luôn luôn là một nỗi đau như vậy, đặc biệt do các tên dài của các tập tin phụ
Gianni Carlo

nó chỉ khả dụng trong ios 11, làm thế nào để sử dụng nó trong ios 10?
kemdo

@kemdo Tại sao bạn nói rằng nó chỉ có sẵn trong iOS 11? Mọi thứ ở đây là iOS 2+ trừ setCompletionBlockđó là iOS 4+
Frédéric Adda

25

Rút gọn câu trả lời hay ho của Brent , đối với ít nhất iOS 7, bạn có thể gói gọn tất cả điều này trong một lệnh gọi [UIView animateWithDuration: delay: options: animations: complete:]:

[UIView animateWithDuration:10 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
  [self.tableView beginUpdates];
  [self.tableView endUpdates];
} completion:^(BOOL finished) {
  // completion code
}];

mặc dù vậy, tôi dường như không thể ghi đè đường cong hoạt ảnh mặc định từ bất kỳ thứ gì khác ngoài EaseInOut.


2
Khi thực hiện chèn hàng theo cách này hoặc theo cách của @ Brent, mặc dù thời lượng được tôn trọng, UITableViewRowAnimation dường như không được tôn trọng và luôn xuất hiện hoạt ảnh từ trên xuống, ngay cả khi tôi chỉ định, chẳng hạn như UITableViewRowAnimationLeft. Thử nghiệm trên iOS 8.4 - có ai có giải pháp không?
Danny

23

Đây là phiên bản Swift của câu trả lời của karwag

    CATransaction.begin()
    tableView.beginUpdates()
    CATransaction.setCompletionBlock { () -> Void in
        // your code here
    }
    tableView.insertRowsAtIndexPaths(indexArray, withRowAnimation: .Top)
    tableView.endUpdates()
    CATransaction.commit()

6

Đối với tôi, tôi cần cái này cho một collectionView. Tôi đã tạo một tiện ích mở rộng đơn giản để giải quyết vấn đề này:

extension UICollectionView {

    func reloadSections(sections: NSIndexSet, completion: () -> Void){
        CATransaction.begin()
        CATransaction.setCompletionBlock(completion)

        self.reloadSections(sections)

        CATransaction.commit()
    }

}

1

performBatchphương thức của tableView chỉ khả dụng bắt đầu từ iOS 11 , bạn có thể sử dụng tiện ích mở rộng sau:

extension UITableView {
func performUpdates(_ updates: @escaping () -> Void, completion: @escaping (Bool) -> Void) {
        if #available(iOS 11.0, *) {
            self.performBatchUpdates({
                updates()
            }, completion: completion)
        } else {
            CATransaction.begin()
            beginUpdates()
            CATransaction.setCompletionBlock {
                completion(true)
            }
            updates()
            endUpdates()
            CATransaction.commit()
        }
    }
}

-8

Bạn có thể cố gắng bọc insertRowsAtIndexPath trong một

- (void)beginUpdates
- (void)endUpdates

giao dịch, sau đó thực hiện flash sau đó.


Xem câu trả lời của karwag ở trên. Bạn cần giải quyết vấn đề về những gì được coi là "sau đó".
JLundell
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.