2012-11-30 23 views
6

Tôi đang gọi bốn phương thức mà tôi muốn thực thi theo thứ tự đồng bộ, hai phương thức đầu tiên là đồng bộ, hai phương thức cuối cùng không đồng bộ (lấy dữ liệu từ URL).Objective-C - Chờ hai phương thức không đồng bộ để hoàn thành

Pseudo-code:

- (void)syncData { 

    // Show activity indicator 
    [object sync]; // Synchronous method 
    [object2 sync]; // Synchronous method 
    BOOL object3Synced = [object3 sync]; // Async method 
    BOOL object4Synced = [object4 sync]; // Async method 
    // Wait for object3 and object4 has finished and then hide activity indicator 
} 

Làm thế nào tôi có thể đạt được điều này?

+3

Pseudo code là không tốt ở đây. Để giúp chúng tôi phải biết bạn sử dụng loại cơ chế không đồng bộ nào. –

+2

@PeterWarbo Nếu 'object3' và' object4' có một số giao diện để thông báo cho bạn khi hoạt động của họ hoàn tất, bạn cần chỉnh sửa bài đăng của mình và hiển thị cho chúng tôi giao diện đó. –

+0

'object3' đang tải xuống tệp thông qua' NSURLRequest' và 'object4' đang sử dụng SDK Facebook để tải xuống dữ liệu (mà tôi tin rằng hậu trường cũng đang sử dụng' NSURLRequest' –

Trả lời

5

Giả sử bạn thực sự có một số loại cách nào để biết khi các phương pháp không đồng bộ được thực hiện, những gì bạn có thể muốn là một cái gì đó như:

- (void)syncData { 

    // Show activity indicator 
    [object sync]; // Synchronous method 
    [object2 sync]; // Synchronous method 

    _object3Synced = _object4Synced = NO; 
    [object3 syncWithCompletionHandler: 
      ^{ 
       _object3Synced = YES; 
       [self considerHidingActivityIndicator]; 
      }]; // Async method 
    [object4 syncWithCompletionHandler: 
      ^{ 
       _object4Synced = YES; 
       [self considerHidingActivityIndicator]; 
      }]; // Async method 
} 

- (void)considerHidingActivityIndicator 
{ 
    if(_object3Synced && _object4Synced) 
    { 
     // hide activity indicator, etc 
    } 
} 
+0

Đó là về cùng một cách tôi đã tưởng tượng rằng tôi sẽ thực hiện nó cũng như với một xử lý hoàn thành khối ... cảm ơn cho đầu vào của bạn –

+0

+1 - tất nhiên object4 phương pháp không thể phụ thuộc vào chế biến của các cuộc gọi phương pháp object3 .. – bryanmac

0

Bạn cần khởi chạy phương thức Async đầu tiên và sử dụng khối hoàn thành. Trong khối hoàn thành của phương thức async đầu tiên, bạn sẽ khởi chạy phương thức async thứ hai của mình. Mặc dù loại này làm cho việc sử dụng các phương thức không đồng bộ không liên quan.

+0

Có, bạn mất lợi ích khi thực hiện hai cuộc gọi không đồng bộ song song nhưng bạn không mất tất cả các lợi ích - ít nhất là nó nằm ngoài chuỗi giao diện người dùng và không treo.Nếu phương thức async thứ hai phụ thuộc vào việc xử lý đầu tiên, thì đây là cách để đi. Nếu không thì các câu trả lời khác sẽ tốt hơn. – bryanmac

+0

Có tất nhiên, nhưng OP không nêu rõ trường hợp chính xác của anh ta là gì. –

+0

Yep, BTW Tôi đã không bỏ phiếu - câu hỏi OPs không rõ ràng với mã giả. Ngoài ra nếu họ phụ thuộc vào nhau, câu trả lời của bạn tốt hơn. – bryanmac

3

Bạn có thể tạo một lớp con của UIActivityInidicator, thêm một tài sản activityCount và thực hiện hai phương pháp bổ sung:

- (void)incrementActivityCount 
{ 
    if(_activityCount == 0) 
    { 
     [self startAnimating]; 
    } 
    _activityCount++; 
} 

- (void)decrementActivityCount 
{ 
    _activityCount--; 
    if(_activityCount <= 0) 
    { 
     _activityCount = 0; 
     [self stopAnimating]; 
    } 
} 

Bây giờ bất cứ khi nào bạn bắt đầu một cái gì đó có sử dụng các hoạt động truy cập gọi incrementActivityCount và trong khối hoàn thành (hoặc nếu không khi nó kết thúc) gọi decrementActivityCount. Bạn có thể làm những thứ khác nếu bạn muốn trong những phương pháp này, ở trên chỉ là một ví dụ đơn giản mà có lẽ là đủ trong hầu hết các trường hợp (đặc biệt là nếu bạn đặt hidesWhenStopped = YES).

+0

thats không nguyên tử và cần tìm cách để làm việc đáng tin cậy. –

+2

@ Daij-Djan Những điều này nên được gọi là chủ đề chính của khóa học vì mọi thứ sẽ chạm vào giao diện người dùng. Bất cứ khi nào bạn đang xử lý các khối hoàn thành để cập nhật giao diện người dùng, bạn nên đảm bảo chúng được gửi đến hàng đợi chính. – jhabbott

25

Sử dụng một rào cản:

void dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);

nộp một khối rào cản để thực hiện đồng bộ và trả lại ngay lập tức.

Khi khối rào cản đạt đến mặt trước của hàng đợi đồng thời riêng tư, nó sẽ không được thực thi ngay lập tức. Thay vào đó, hàng chờ đợi cho đến khi các khối hiện đang thực thi của nó kết thúc thực hiện. Tại thời điểm đó, hàng đợi thực thi khối rào chắn của chính nó. Bất kỳ khối nào được gửi sau khối rào cản sẽ không được thực hiện cho đến khi khối chắn hoàn thành.

Ví dụ này xuất ra 1 2 3 4 done mặc dù không đồng bộ, có thể là 1 2 4 3 done. Vì tôi hiểu bạn muốn xử lý một chỉ số hoạt động, điều này không quan trọng.

#import <Foundation/Foundation.h> 
int main(int argc, char *argv[]) { 
    @autoreleasepool { 
     dispatch_queue_t queue = dispatch_queue_create("com.myqueue", 0); 
     dispatch_sync(queue, ^(){NSLog(@"1");}); 
     dispatch_sync(queue, ^(){NSLog(@"2");}); 
     dispatch_async(queue, ^(){NSLog(@"3");}); 
     dispatch_async(queue, ^(){NSLog(@"4");}); 
     dispatch_barrier_sync(queue, ^(){NSLog(@"done");}); 
    } 
} 

Đối với những cách khác để kiểm tra mã không đồng bộ, xem: https://stackoverflow.com/a/11179523/412916

+0

Nếu bạn không quan tâm đến việc thực hiện đồng thời các phương thức không đồng bộ, hãy sử dụng 'DISPATCH_QUEUE_CONCURRENT' (có sẵn trong iOS 5) thay vì 0 khi tạo hàng đợi. – Jano

+0

Điều này giả định rằng cả hai hoạt động không đồng bộ đều nằm trên cùng một hàng đợi và hàng đợi đó có thể truy cập được từ mã sẽ lên lịch cho rào cản. –

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