2012-06-24 30 views
8

Tôi đang làm việc trên một tác vụ (chỉ iOS5 +) liên quan đến việc tải xuống hàng nghìn hình ảnh từ máy chủ. Các hình ảnh thuộc về các danh mục nhất định và mỗi danh mục có thể có hàng trăm hình ảnh. Những gì tôi cần làm là: -AFNetworking + NsOperationQueue - Tải xuống hàng nghìn Hình ảnh

1) Đảm bảo ứng dụng tải xuống bất kỳ hình ảnh nào bị thiếu trong nền nếu ứng dụng đang hoạt động (ngay cả khi người dùng đang duyệt một số khu vực khác của ứng dụng không liên quan đến ảnh) .

2) Khi người dùng nhấp vào Danh mục ảnh, hình ảnh trong Danh mục đó phải được tải xuống là ưu tiên cao vì đó là những hình ảnh cần được hiển thị ngay lập tức.

Tất cả những điều trên chỉ xảy ra nếu hình ảnh không khả dụng ngoại tuyến. Sau khi tải xuống, hình ảnh sẽ được sử dụng từ bộ nhớ cục bộ.

Để giải quyết việc này, logic Tôi đang sử dụng là: -

1) Trong AppDelegate.m, trong applicationDidBecomeActive, tôi bắt đầu downlading bất kỳ hình ảnh thiếu. Để thực hiện điều này, tôi thực hiện truy vấn Dữ liệu cốt lõi, tìm hiểu hình ảnh nào bị thiếu và bắt đầu tải xuống chúng trong chuỗi có mức độ ưu tiên BACKGROUND. Một cái gì đó như thế này: -

dispatch_queue_t imageDownloadQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0); 
dispatch_async(imageDownloadQueue, ^{ 
    [DataDownloader downloadMissingImages]; 
}); 
dispatch_release(imageDownloadQueue); 

Các downloadMissingImages mã trông như thế này: -

NSOperationQueue *downloadQueue = [[NSOperationQueue alloc] init]; 
     downloadQueue.maxConcurrentOperationCount = 20; 

     for(MyImage *img in matches) 
     { 
      NSURLRequest *request = [NSURLRequest requestWithURL:img.photoUrl]; 
      AFImageRequestOperation *operation = [AFImageRequestOperation imageRequestOperationWithRequest:request success:^(UIImage *image) { 

       [MyImage imageFromAPI:image inManagedObjectContext:document.managedObjectContext]; 

       NSLog(@"Successfully downloaded image for %@", img.title);  
      }]; 

      [downloadQueue addOperation:operation]; 
     } 

này hoạt động, nhưng nó ngăn chặn các giao diện người dùng chính và treo ứng dụng sau một thời gian. Đây là khi tôi cố tải xuống khoảng 700 hình ảnh. Với nhiều hình ảnh hơn, nó chắc chắn sẽ sụp đổ.

2) Khi người dùng nhấp vào danh mục, trước tiên tôi cần phải tải xuống những hình ảnh đó vì chúng phải được hiển thị cho người dùng ngay lập tức. Tôi không chắc chắn làm thế nào tôi có thể gián đoạn cuộc gọi missingImages và nói với nó để bắt đầu tải về hình ảnh nhất định trước khi những người khác. Vì vậy, về cơ bản, tôi cần phải tải xuống tất cả các hình ảnh bị thiếu trong nền nhưng nếu người dùng đang duyệt danh mục ảnh, những hình ảnh đó phải có mức độ ưu tiên cao trong hàng đợi tải xuống.

Tôi đang mất mát cách làm việc này hiệu quả. Có suy nghĩ gì không?

bản ghi

Vụ tai nạn giống như thế này

PAPP(36373,0xb065f000) malloc: *** mmap(size=16777216) failed (error code=12) 
*** error: can't allocate region 
*** set a breakpoint in malloc_error_break to debug 
PAPP(36373,0xb065f000) malloc: *** mmap(size=16777216) failed (error code=12) 
*** error: can't allocate region 
*** set a breakpoint in malloc_error_break to debug 
Jun 24 11:39:45 MacBook-Pro.local PAPP[36373] <Error>: ImageIO: JPEG Insufficient memory (case 4) 

Cảm ơn trước.

Trả lời

3

Về vụ tai nạn, tôi đoán rằng ứng dụng của bạn bị giết do một trong hai lựa chọn:

  1. ứng dụng ngày càng trở nên không đáp ứng (và do đó không đáp ứng với quá trình trọng điểm iOS);

  2. quá nhiều bộ nhớ được sử dụng trong vòng lặp tạo hơn 700 hoạt động yêu cầu.

Để làm rõ điều gì đang xảy ra, bạn nên cung cấp thêm thông tin về sự cố (nhật ký bảng điều khiển). Trong mọi trường hợp, sửa chữa sẽ được tải hình ảnh trong khối có thể 10 hoặc 20 mỗi (bạn có thể đi ngay cả 1 của 1, nếu bạn thích, tôi không thấy nhiều vấn đề với điều đó).

Về điểm thứ hai, những gì về vấn đề này:

  1. tải một hình ảnh ưu tiên cao hơn trong các chủ đề chính (thông qua một tải async, tất nhiên, để tránh chặn các giao diện người dùng);

  2. trước khi bắt đầu tải xuống hình ảnh "ngoại tuyến", bạn kiểm tra xem hình ảnh đã được tải xuống trong khi đó thông qua tải xuống "ưu tiên cao hơn".

Xử lý điểm 2 tốt, bạn có lẽ sẽ cần phải xếp hàng hoạt động tùy chỉnh của bạn thay vì một AFImageRequestOperation để làm việc kiểm tra trước khi tải thực tế.

EDIT:

Về tải hình ảnh trong đoạn, những gì bạn có thể làm là sử dụng các nhóm văn vào nhóm hoạt động mạng của bạn:

dispatch_group_t group = dispatch_group_create(); 

<your_core_data_query> 

for (...) { 
    dispatch_group_enter(group); 

     NSURLRequest *request = [NSURLRequest requestWithURL:img.photoUrl]; 
     AFImageRequestOperation *operation = [AFImageRequestOperation imageRequestOperationWithRequest:request success:^(UIImage *image) { 
      [MyImage imageFromAPI:image inManagedObjectContext:document.managedObjectContext]; 
      NSLog(@"Successfully downloaded image for %@", img.title); 

      dispatch_group_leave(group);  //<== NOTICE THIS 
     }]; 

} 

dispatch_group_wait(group, DISPATCH_TIME_FOREVER); 
dispatch_release(group); 

Trong ví dụ này, tôi đang sử dụng một nhóm công văn vào nhóm một số hoạt động không đồng bộ và chờ cho chúng được thực hiện tất cả; khi dispatch_group_wait trả về, bạn có thể thực hiện một vòng khác (truy vấn dữ liệu cốt lõi rồi gửi các ops).

Giới thiệu về câu hỏi khác của bạn (làm cách nào để kiểm tra xem hàng đợi ưu tiên cao hơn đã tải xuống một hình ảnh nhất định hay chưa), bạn nên thực hiện truy vấn dữ liệu lõi trước khi thực hiện mỗi AFImageRequestOperation; một khả năng là bắt nguồn từ lớp của riêng bạn và ghi đè phương thức start để thực hiện kiểm tra. Trên cả hai tài khoản, bạn có thể đơn giản hóa nhiều bản ghi của tất cả điều này bằng cách tải xuống hình ảnh một lúc (tức là vòng for (...) sẽ không có ở đó; bạn chỉ cần truy vấn hình ảnh tiếp theo để tải xuống và tải xuống; trước khi tải xuống bạn kiểm tra xem nó không phải là đã có.

tôi sẽ đề nghị đi con đường này dễ dàng hơn.

Hy vọng nó giúp.

+0

Hi Sergio, có bạn có bất kỳ mẫu mã để chứng minh tải chunked như bạn đề nghị? –

+0

Cũng , làm thế nào để kiểm tra xem một hàng đợi ưu tiên cao hơn đã tải xuống một ce có được hình ảnh? Bất kỳ mã mẫu nào cho điều đó? –

+0

Đã sửa đổi câu hỏi để bao gồm nhật ký sự cố - Tôi tạo hình thu nhỏ từ mỗi hình ảnh tải xuống .. vì vậy tôi đoán 700 hình ảnh chắc chắn gây ra rò rỉ bộ nhớ ở đây .. –

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