2012-02-01 49 views
9

tôi có một câu hỏi liên quan đến việc cập nhật giao diện người dùng trên chuỗi chính bằng cách sử dụng hàng đợi.Cập nhật giao diện người dùng trên dispatch_get_main_queue()

Vâng, giả sử chúng tôi tạo có UITableView những gì hiển thị UILabel với UIImageView. UIImage của được nạp không đồng bộ trong prepareCellfor .. sử dụng:

dispatch_async(t_queue, ^{ 
    //load image 
    //dispatch_async(dispatch_get_main_queue(),^{ 
    cell.imageView = image; 
    } 
}); 

Nhưng trong khi các khối được lấy hình ảnh người dùng nhấn một tế bào (hoặc nút quay lại trên bộ điều khiển giao diện điều hướng) một tải de DetailViewController cho tế bào đó (hoặc quay trở lại trong ứng dụng).

Câu hỏi của tôi là: điều gì xảy ra khi khối khởi chạy luồng chính để cập nhật imageView cho ô? nó đang cố gắng cập nhật một UIView mà không được tải trên cửa sổ hoặc thậm chí nó có thể đã được dỡ bỏ ...

Cảm ơn

Trả lời

14

Đây là một câu hỏi hay. Và câu trả lời khi sử dụng ARC về bản chất là bản thân khối giữ lại đối tượng, để nó sẽ xung quanh sau. Đây là một trong những bộ nhớ tinh tế. Nếu số UITableView mà từ đó ô này được phân bổ và giải phóng tất cả các ô của nó, ô này sẽ được giữ lại (mặc dù không có màn hình) và sẽ được gán cell.imageView = image; hoàn thành, sau đó nó sẽ được giải phóng.

Tôi là một fan hâm mộ lớn của các thử nghiệm được kiểm soát và đặt ra để kiểm tra điều này, nhưng UITableView có nhiều bộ phận chuyển động (không có ý định chơi chữ). Vì vậy, tôi đã tạo ra một thí nghiệm rất đơn giản, sử dụng một NSObject lớp con đơn giản như sau:

@implementation SayHello 
-(void)sayHello{ 
    NSLog(@"Hello"); 
} 
-(void)dealloc{ 
    NSLog(@"SayHello dead"); 
} 
@end 

Rõ ràng lớp học này được thiết kế để cung cấp cho tôi một chức năng để gọi trong một khối (sayHello) và sẽ tạo ra một NSLog khi de-phân bổ .

Tôi chạy thử nghiệm của tôi như thế này:

SayHello *hello = [[SayHello alloc] init]; 
dispatch_async(dispatch_get_global_queue(0, 0), ^{ 
    double delayInSeconds = 30.0; 
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 
     [hello sayHello]; 
    }); 
}); 

30 giây cho ngay cả những thời gian runloop lười biếng nhất để deallocate "hello" đối tượng (nếu, trên thực tế, nó không được giữ lại). Nhưng trong 30 giây giao diện điều khiển là im lặng. Sau 30 giây đã hết hạn tôi nhận được "Hello" ngay lập tức theo sau là "SayHello chết" tin nhắn.

Vậy đây là "hình ảnh xác thực"? Vâng, rõ ràng là nếu bạn không nhận ra rằng Blocks/ARC đang làm điều này, nó có thể kết thúc việc giữ những thứ bạn nghĩ sẽ biến mất. Nhưng cũng với ví dụ của bạn về một UITableViewCell; nếu ô của bạn được hiển thị một lần và gửi yêu cầu qua mạng cho một hình ảnh, nhưng trong khi khối đang chờ hình ảnh thì ô đó sẽ được sử dụng lại? Bây giờ có một khối thứ hai với tham chiếu đến ô đó đang cố gắng thiết lập hình ảnh của nó. Vâng, bây giờ bạn có một cuộc đua trong đó kẻ thua cuộc sẽ quyết định hình ảnh nào được hiển thị.

Các vấn đề liên quan