2011-08-08 31 views
5

Vì vậy, tôi có mã này:dispatch_async bị trễ ở đâu đó, không thể tìm thấy ở đâu. có vấn đề về NSLog không?

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{ 

//Bunch of code 

NSLog(@"Test"); 

}); 

chạy và lợi nhuận NSLog ngay lập tức. Nhưng kết quả của mã chỉ xuất hiện trên màn hình một vài giây chậm trễ. Có một vấn đề với nslog đang được sử dụng ở đây, có nghĩa là nó được gọi trước khi nó sẽ thường, làm cho nó có vẻ nhanh chóng khi thực sự nó không phải là. Tôi đang bối rối như nơi mà sự chậm trễ này là đến từ, như NSLog là phải ở phần cuối của tất cả các mã chạy sau đó.

Ngoài ra, một giải pháp khác cho vấn đề của tôi là có thể nhận NSLog khi mọi phương thức được gọi (một chút như NSZombiesEnabled tôi giả sử) để tôi có thể đảm bảo rằng thời gian phản hồi ngọt ngào của ứng dụng của tôi?

+3

Tại sao bạn mong đợi nhật ký của mình hiển thị ngay lập tức? "Hàng loạt mã" của bạn có thể mất vài giây để chạy, trì hoãn nhật ký bằng nhiều, bởi vì nó sẽ chỉ thực hiện sau khi phần còn lại của mã của bạn có. –

+0

Đây là điều làm tôi bối rối. Đó là sau mỗi bit mã, và xuất hiện ngay lập tức trong khi mã mất vài giây để hiển thị kết quả trên màn hình. – Andrew

+1

OK, vì vậy bạn đang nói rằng câu lệnh NSLog có văn bản hiển thị ngay lập tức trên bàn điều khiển, nhưng "bó mã" của bạn chứa trong đó các cập nhật giao diện người dùng khác không có hiệu lực trên màn hình ngay lập tức?Nếu đó là trường hợp, loại cập nhật giao diện người dùng là gì? Chúng được gửi đi không đồng bộ trên chủ đề chính? Có quá trình nào có thể bị chặn trong vòng lặp chính trên chuỗi chính sau khi khối này được gửi đi, có khả năng ngăn cập nhật giao diện người dùng không? –

Trả lời

11

Gần đây tôi cũng có một vấn đề tương tự. Nhiều khả năng các bản cập nhật bị trì hoãn của bạn là những thứ bạn đang thực hiện trên giao diện người dùng. Và đây là vấn đề: bạn không chạy trong luồng chính của ứng dụng (còn được gọi là chuỗi giao diện người dùng). Vì vậy, bất cứ điều gì bạn thay đổi giao diện người dùng sẽ không thực sự được hiển thị cho đến khi ... nó cảm thấy như hiển thị, có xu hướng xảy ra với một vẽ lại được kích hoạt bởi một cái gì đó khác trong ứng dụng.

Những gì bạn phải làm là bên trong hàng đợi khối của bạn cập nhật đồ họa của bạn trong thread UI như thế này:

dispatch_async(dispatch_get_main_queue(), ^{ 
     // Do GUI stuff. 
    }); 

Đôi khi khối của bạn có thể là lớn hay chỉ sử dụng mã mà trước đó đã chạy trên các chủ đề chính, vì vậy rất khó để di chuyển tất cả nó đến một nơi cụ thể để chạy nó trên hàng đợi chính. Đối với những tình huống này, xếp hàng làm mới buộc trong thread UI vào cuối khối của bạn:

dispatch_async(dispatch_get_main_queue(), ^{ 
     [self.somewidget setNeedsDisplay]; 
     [self.view setNeedsDisplay]; 
     [self.dontforgetme setNeedsDisplay]; 
    }); 

Liên quan đến bạn "ứng dụng chiếm thời gian phản ứng ngọt ngào của ứng dụng của tôi", có vẻ như hai người là bạn cố gắng sử dụng GDC để tránh chặn giao diện người dùng. Để đảm bảo lập trình rằng bạn không xảy ra hoạt động chuyên sâu CPU trong chuỗi giao diện người dùng và ngược lại, bạn chạy cập nhật GUI trong khối giao diện người dùng, tôi đã tự tạo các macro sau:

/// Stick this in code you want to assert if run on the main UI thread. 
#define DONT_BLOCK_UI() \ 
    NSAssert(![NSThread isMainThread], @"Don't block the UI thread please!") 

/// Stick this in code you want to assert if run on a background thread. 
#define BLOCK_UI() \ 
    NSAssert([NSThread isMainThread], @"You aren't running in the UI thread!") 

bạn có thể thấy bằng các bình luận, tôi có xu hướng sử dụng các macro này ở đầu các phương thức mà tôi muốn đảm bảo rằng tôi không sử dụng sai sót ở sai địa điểm. Tôi đã đặt những macro này và nhiều thứ ngẫu nhiên khác tại số https://github.com/gradha/ELHASO-iOS-snippets mà bạn có thể thấy hữu ích.

11

UIKit không an toàn cho chủ đề. Bất kỳ cuộc gọi nào bạn thực hiện có ảnh hưởng đến giao diện người dùng của bạn cần phải được thực hiện trên chuỗi chính hoặc bạn sẽ nhận được hành vi lạ thường, không thể đoán trước. Ví dụ:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

    // Background code that doesn't need to update the UI here 

    dispatch_async(dispatch_get_main_queue(), ^{ 
     // UI code here 
    }); 
}); 
+0

Đây là một câu trả lời tuyệt vời bởi vì tôi nghĩ rằng hầu hết công việc đáp ứng sự kiện cần phải xảy ra: lật từ hàng đợi Chính đến hàng đợi Công việc (chủ yếu) và sau đó quay trở lại hàng đợi Chính cho bất kỳ mã UIKit nào (ít nhất có thể) . Mã này cũng có liên quan, tôi nghĩ: http://stackoverflow.com/a/8186206/8047 –

+0

Xin lỗi, chỉ cần đọc câu trả lời tôi đã liên kết lại: nếu bạn đang gửi đi không đồng bộ với chủ đề chính, bạn không có phải lo lắng nếu bạn đang ở trên chuỗi chính ở vị trí đầu tiên. –

+0

Điều này phải được chấp nhận làm câu trả lời đúng. Cảm ơn! – NSAddict

-1

Thay vì sử dụng // Bunch mã, bạn nên dán đoạn mã thực, nếu không thật khó để tìm thấy vấn đề của bạn và lãng phí thời gian của chúng tôi. Tôi đoán bạn có lẽ bạn cập nhật ui trong "bó mã" mà nên trong chủ đề chính.

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