48

Tôi đang trong quá trình xem xét lại cách tiếp cận của tôi đối với kiến ​​trúc yêu cầu của một ứng dụng lớn mà tôi đang phát triển. Tôi hiện đang sử dụng ASIHTTPRequest để thực sự yêu cầu, nhưng vì tôi cần nhiều loại yêu cầu khác nhau do kết quả của nhiều hành động khác nhau được thực hiện trong các trình điều khiển chế độ xem khác nhau, tôi đang cố gắng tìm ra hệ thống tốt nhất để tổ chức các yêu cầu này.Kiến trúc tốt nhất cho ứng dụng iOS tạo nhiều yêu cầu mạng?

Tôi hiện đang xây dựng "người yêu cầu" đơn lẻ được đại diện ứng dụng giữ lại và ngồi xung quanh lắng nghe NSNotifications báo hiệu yêu cầu cần được thực hiện; họ đưa ra yêu cầu, lắng nghe phản hồi và gửi một NSNotification mới với dữ liệu phản hồi. Điều này giải quyết hầu hết các vấn đề của tôi, nhưng không thanh lịch xử lý các yêu cầu không thành công hoặc yêu cầu đồng thời cho cùng một người yêu cầu singleton.

Bất kỳ ai cũng có thành công trong việc tạo ra một cấu trúc OO rõ ràng để tạo nhiều loại yêu cầu khác nhau trong ứng dụng iOS?

+2

Câu hỏi hay: Tôi cũng đã nghiên cứu câu trả lời cho điều này, là người đã tạo trình quản lý kết nối cho NSURLConnection hoạt động tốt cho một kết nối nhưng không tốt cho một kết nối. –

Trả lời

69

Sau khi thử một số phương pháp tiếp cận, đây là một trong những kiến ​​trúc đó là đem lại cho tôi kết quả tuyệt vời, rất dễ dàng để ghi lại, hiểu, duy trì và mở rộng:

  • Tôi có một đối tượng duy nhất chăm sóc khả năng kết nối mạng, chúng ta hãy gọi nó là "người quản lý mạng". Thông thường đối tượng này là một singleton (được tạo ra bằng cách sử dụng Matt Gallagher's Cocoa singleton macro).
  • Vì bạn sử dụng ASIHTTPRequest (mà tôi luôn làm, API tuyệt vời), tôi thêm một ASINetworkQueue ivar vào trong trình quản lý mạng của tôi. Tôi làm cho người quản lý mạng là đại biểu của hàng đợi đó.
  • Tôi tạo các lớp con của ASIHTTPRequest cho mỗi loại yêu cầu mạng mà ứng dụng của tôi yêu cầu (thông thường, đối với mỗi tương tác REST phụ trợ hoặc điểm cuối SOAP). Điều này có lợi ích khác (xem bên dưới để biết chi tiết :)
  • Mỗi lần một bộ điều khiển của tôi yêu cầu một số dữ liệu (làm mới, viewDidAppear, v.v.), trình quản lý mạng tạo một thể hiện của lớp con ASIHTTPRequest bắt buộc và sau đó thêm nó vào hàng đợi .
  • ASINetworkQueue xử lý các sự cố băng thông (tùy thuộc vào việc bạn đang sử dụng 3G, EDGE hoặc GPRS hay Wifi, bạn có băng thông nhiều hơn và bạn có thể xử lý nhiều yêu cầu hơn, v.v.). Điều này được thực hiện bởi hàng đợi, đó là mát mẻ (ít nhất, đó là một trong những điều tôi hiểu hàng đợi này, tôi hy vọng tôi không nhầm :).
  • Bất cứ khi nào yêu cầu kết thúc hoặc không thành công, trình quản lý mạng được gọi (hãy nhớ, trình quản lý mạng là đại biểu của hàng đợi).
  • Người quản lý mạng không biết ngồi xổm về việc phải làm gì với kết quả của mỗi yêu cầu; do đó, nó chỉ gọi một phương thức theo yêu cầu! Hãy nhớ rằng, các yêu cầu là các lớp con của ASIHTTPRequest, vì vậy bạn có thể chỉ cần đặt mã quản lý kết quả của yêu cầu (thường, deserialization JSON hoặc XML thành các đối tượng thực, kích hoạt các kết nối mạng khác, cập nhật các kho dữ liệu Core, v.v.). Đưa mã vào mỗi phân lớp yêu cầu riêng biệt, sử dụng một phương thức đa hình với tên chung trên các lớp yêu cầu, làm cho nó rất dễ dàng để gỡ lỗi và quản lý IMHO.
  • Cuối cùng, tôi thông báo cho các bộ điều khiển ở trên về các sự kiện thú vị bằng cách sử dụng thông báo; Sử dụng giao thức đại biểu không phải là một ý tưởng hay, bởi vì trong ứng dụng của bạn, bạn thường có nhiều bộ điều khiển nói chuyện với người quản lý mạng của bạn, và sau đó thông báo linh hoạt hơn (bạn có thể có nhiều bộ điều khiển phản hồi cùng một thông báo, v.v.).

Dù sao, đây là cách tôi đã làm việc đó một thời gian, và thẳng thắn là nó hoạt động khá tốt.Tôi có thể mở rộng hệ thống theo chiều ngang, thêm nhiều lớp con ASIHTTPRequest như tôi cần chúng, và cốt lõi của trình quản lý mạng vẫn nguyên vẹn.

Hy vọng điều đó sẽ hữu ích!

+0

câu trả lời hay! làm thế nào để bạn kiểm tra hệ thống của bạn? một mối quan tâm lớn của tôi là đến với một kiến ​​trúc dễ dàng để kiểm tra đơn vị. – kevboh

+0

cảm ơn, giải thích tuyệt vời. – Epaga

+5

Một điều nhanh chóng nảy sinh trong đầu, bạn có thể sử dụng các khối thay vì thông báo nếu bạn chỉ có một lớp quan tâm đến phản hồi của bạn. –

0

Dự án fully-loaded là một tài liệu đọc tốt.

+0

Tôi đã nhìn thấy đầy đủ trước khi nó xử lý một vấn đề cụ thể tốt, nhưng tôi đang tìm một giải pháp xử lý các loại yêu cầu khác nhau có các phản hồi khác nhau. Cách các yêu cầu xử lý được tải đầy đủ tương tự như những gì tôi đã nêu chi tiết trong câu hỏi của mình, với các thông báo nsnotifications và asihttprequest thực hiện việc nâng hạng nặng. Tôi đang tìm kiếm thứ gì đó có thể mở rộng và mạnh mẽ hơn, ngay cả khi đó chỉ là một cách sáng tạo để tổ chức thông báo và yêu cầu. – kevboh

+1

Ví dụ mã khác trong tâm trí của tôi là thư mục 'Networking' trong mẫu MVCNetworking từ Apple, mà tôi không có bất kỳ kinh nghiệm nào để đưa ra bất kỳ bình luận nào. – ohho

+0

Thú vị. Tôi sẽ phải kiểm tra điều này. – kevboh

1

Đây là cách tôi thường làm điều đó. Tôi cũng có một đối tượng đơn được sử dụng để thực hiện các yêu cầu mạng. Đối với các yêu cầu phải được thực hiện thường xuyên, tôi có một NSOperationQueue chấp nhận AFHTTPRequestOperations (hoặc AFJSONRequestOperations) vì tôi thường sử dụng AFNetworking để thực hiện các yêu cầu. Đối với những điều này, có một thuộc tính completionBlock và failureBlock được thực hiện khi thành công hoặc thất bại của yêu cầu. Trên đối tượng singleton của tôi, tôi sẽ có một phương thức để khởi tạo một yêu cầu mạng cụ thể, và như các tham số cho phương thức đó, tôi sẽ bao gồm một khối thành công và thất bại có thể được chuyển vào các khối được định nghĩa trong phương thức. Bằng cách này, toàn bộ ứng dụng có thể thực hiện một yêu cầu mạng, và phạm vi của ứng dụng tại thời điểm đó có sẵn cho singleton trong khối được truyền cho phương thức. Ví dụ ... (sử dụng ARC)

 @implementation NetworkManager 

    -(void)makeRequestWithSuccess:(void(^)(void))successBlock failure:(void(^)(NSError *error))failureBlock 

    { 
     NSURL *url = [NSURL URLWithString:@"some URL"]; 

     NSURLRequest *request = [NSURLRequest requestWithURL:url]; 

     AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:request]; 

     [op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { 
      [responseObject doSomething]; 

      if (successBlock) 
       dispatch_async(dispatch_get_main_queue(), successBlock); 

     } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 

      if (failureBlock) 
       dispatch_async(dispatch_get_main_queue(), ^{ 
        failureBlock(error); 
       }); 
     }]; 

     [self.operationQueue addOperation:op]; 
    } 
@end 

Và bạn luôn có thể thực hiện chặn thành công khi tham gia bất kỳ thông số nào bạn cần.

0

Hãy thử STNetTaskQueue, điều này có thể làm cho yêu cầu của bạn có thể sử dụng lại và duy trì được.

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