2013-10-22 16 views
5

Tôi đã cố gắng sử dụng dispatch_async trong một phương thức trả về kết quả. Tuy nhiên, tôi quan sát thấy phương thức trả về trước khi thực thi khối dispatch_async. Do đó tôi không nhận được kết quả như mong đợi. Đây là một số mã chứng minh vấn đề của tôi.dispatch_async trong mục tiêu trả về c

-(BOOL) isContactExists { 
    BOOL isContactExistsInXYZ = YES; 
    UserId *userId = contact.userId; 
    dispatch_async(dispatch_get_main_queue(),^
    { 
     iOSContact *contact = [iOSContact contactForUserId:userId]; 
     if (nil == contact) 
     { 
      isContactExistsInXYZ = NO; 
     } 
    });  

    return isContactExistsInXYZ; 
} 

Phương pháp này isContactExists được gọi ở một nơi khác và dựa trên phản hồi từ phương pháp đó tôi phải thực hiện một số nội dung. Nhưng mỗi lần, giá trị của isContactExistsInXYZ không phải là những gì tôi mong đợi. Bất cứ ai có thể vui lòng giải thích làm thế nào để xử lý dispatch_async trong tình huống này?

Cảm ơn.

+0

dispatch_async là không đồng bộ đó là trung bình mà yhe trở lại sẽ đạt được trước khi kết thúc công văn async – Francescu

+0

@ francescu, Rằng tôi hiểu với phân tích của tôi, bạn có thể xin vui lòng giúp đỡ để làm thế nào để xử lý nó theo cách khác, một đoạn mã hoặc thông tin logic. Cảm ơn –

Trả lời

6

Bạn cần phải tôn trọng rằng những gì bạn đang cố gắng làm là không đồng bộ và nắm lấy điều đó. Điều này có nghĩa là không sử dụng giá trị trả lại. Thay vào đó, bạn có thể viết phương thức của mình để lấy khối gọi lại làm tham số. Sau đó, khi kiểm tra không đồng bộ của bạn hoàn tất, bạn có thể gọi khối đó với kết quả.


Vì vậy, phương pháp chữ ký của bạn sẽ trở thành:

- (void)checkIfContactExistsWithCompletion:(ContactExistsBlock)completion { 

đâu ContactExistsBlock là một định nghĩa block với không trở lại và có lẽ một BOOL tham số duy nhất.

typedef void (^ContactExistsBlock) (BOOL exists); 
+0

Bạn có thể xây dựng mã mẫu hoặc bạn đang nói tôi sử dụng khối xử lý "hoàn thành" –

3

Lý do là dispatch_async(dispatch_get_main_queue(), ^ không chờ cho đến khi thực hiện xong. Có thể bạn đang làm rối tung mọi thứ ở đó. Thông thường, điều này được sử dụng để cập nhật giao diện người dùng không đồng bộ cùng với nội dung máy chủ khác nhận được tải xuống trong một số chủ đề khác. Hãy thử sử dụng dispatch_sync để thay thế.

+0

Ở đây một điều tôi phải đề cập là yêu cầu của tôi là phải chạy thao tác trong chuỗi nền, vì vậy tôi đã chọn sử dụng 'dispatch_async' trên' dispatch_sync'. Bạn có thể vui lòng cho tôi một thông tin hợp lý hoặc để xử lý như vậy theo cách khác. Cảm ơn. –

+0

Bạn cần xem xét mẫu ủy quyền. Có rất nhiều ví dụ trong khung công tác iOS. Xem cách NSConnection hoạt động. Nó cung cấp cho bạn một cuộc gọi trở lại ngay sau khi một số đoạn dữ liệu đã sẵn sàng. Vì vậy, có lẽ, bạn cần phải thực hiện hoạt động của bạn không đồng bộ và sau đó xử lý cuộc gọi trở lại thông qua các phương thức đại biểu. – Abhinav

10

Nếu bạn định tuyến đường, phương pháp của bạn cần phải trông giống như thế này.

- (void)isContactExistsWithCompletionHandler:(void(^)(BOOL exists)) completion 
{ 
    dispatch_async(dispatch_get_main_queue(),^
    { 
     BOOL isContactExistsInXYZ = YES; 
     UserId *userId = contact.userId; 
     iOSContact *contact = [iOSContact contactForUserId:userId]; 
     if (nil == contact) 
     { 
      isContactExistsInXYZ = NO; 
     } 
     completion(isContactExistsInXYZ); 
    }); 
} 

Và nơi bạn đang gọi nó như thế này.

[someObject isContactExistsWithCompletionHandler:^(BOOL exists) { 
    // do something with your BOOL 
}]; 

Bạn cũng nên xem xét đặt các hoạt động nặng của mình vào một hàng đợi khác so với chính. Như thế này.

- (void)isContactExistsWithCompletionHandler:(void(^)(BOOL exists)) completion 
{ 
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL); 
    dispatch_async(queue,^
    { 
     BOOL isContactExistsInXYZ = YES; 
     UserId *userId = contact.userId; 
     iOSContact *contact = [iOSContact contactForUserId:userId]; 
     if (nil == contact) 
     { 
      isContactExistsInXYZ = NO; 
     } 
     dispatch_async(dispatch_get_main_queue(),^
     { 
      completion(isContactExistsInXYZ); 
     }); 
    }); 
}