5

Tôi đã triển khai ứng dụng trình quản lý tải xuống nhắm mục tiêu iOS 7+ bằng cách sử dụng NSURLSession. Trình quản lý tải xuống có danh sách các tệp được liệt kê sẽ được tải xuống theo thứ tự ưu tiên. Việc tải xuống hoạt động tốt trong khi ứng dụng ở chế độ nền và cuộc gọi ủy nhiệm sẽ được gọi chính xác. Nhưng khi ứng dụng đi ở chế độ nền, mặc dù việc tải xuống được hoàn thành phải mất quá nhiều thời gian choTải xuống danh sách 100 tệp từng cái một bằng cách sử dụng NSURLSession trong nền

NSURLSession delegate:- **URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)downloadURL

để gọi. Một số lần các đại biểu không được gọi là ở tất cả và khi tôi đến foreground sau đó nhiệm vụ tải xuống đại biểu được gọi là. Bất kỳ lý do cho sự chậm trễ này?

+0

Tôi đang đối mặt với cùng một vấn đề. Tôi đang đi qua một mảng các mục và phương thức ủy nhiệm chỉ được kích hoạt khi tôi khởi chạy lại ứng dụng. –

+0

Các cuộc gọi lại không nhất quán và các lượt tải xuống mất quá nhiều thời gian để bắt đầu.Với các tệp nhỏ tôi đã dùng thử với trình mô phỏng và tải xuống một số tệp hình ảnh nhỏ. Số lần gọi lại để tải xuống hoàn tất được kích hoạt sau khi tải xuống hoàn tất 2 hoặc 3 phút trước.Đây gây lag cho việc bắt đầu các tập tin tiếp theo được tải xuống. Vấn đề đang xảy ra khi tôi đưa ứng dụng của tôi vào background.In foreground các chức năng tương tự hoạt động tốt. – Sulabh

+0

Bạn có làm theo tất cả các hướng dẫn trong https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/URLLoadingSystem/Articles/UsingNSURLSession.html#//apple_ref/doc/uid/TP40013509-SW44 (Chuyển nền) Cân nhắc)? Ý tôi là, bạn sử dụng cấu hình phiên nền và triển khai tất cả các cuộc gọi lại cần thiết trong appDelegate và NSURLSessionDelegate? – user2260054

Trả lời

0

Tôi gặp vấn đề rất giống với nhiệm vụ nền sẽ bắt đầu nhưng sau đó xuất hiện tạm dừng. Nhiệm vụ sau đó sẽ hoàn thành khi ứng dụng quay trở lại nền trước.

Tôi xác nhận rằng đây là trường hợp bằng cách đăng nhập đầu ra từ -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite

tôi thấy rằng cách để có được xung quanh vấn đề này là để làm với cách bạn lưu trữ, xử lý và thực hiện xử lý hoàn thành của bạn.

Trong trường hợp của tôi quá trình này bắt đầu với

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{ 

[self.fmStore performBackgroundRefresh:^(UIBackgroundFetchResult result) { 

    //Set application badge if new data is available 
    if (result==UIBackgroundFetchResultNewData) [UIApplication sharedApplication].applicationIconBadgeNumber++; 
    completionHandler(result); 

}]; 
} 

nơi thông báo từ xa bắt đầu quá trình download.

Phương pháp quản lý việc tải xuống trả về một giá trị phụ thuộc vào sự sẵn có của dữ liệu mới

-(void)performBackgroundRefresh:(void (^)(UIBackgroundFetchResult))completion{ 
    if(newData) completion(UIBackgroundFetchResultNewData); 
    else completion(UIBackgroundFetchResultNoData); 
} 

Tại thời điểm này nó trả lại cho ApplicationDelegate nơi xử lý hoàn thành được lưu trữ

- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler{ 
//Store completion handler for background session 
self.sessionCompletionHandler=completionHandler; 
} 

Cuối cùng , đoạn mã này được thực hiện gọi là trình xử lý hoàn tất và tạo thông báo thích hợp

- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session{ 
[session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) { 
    if (![downloadTasks count]) { 


     FM_AppDelegate *appDelegate=(FM_AppDelegate *)[[UIApplication sharedApplication] delegate]; 
     if (appDelegate.sessionCompletionHandler) { 
      void (^completionHandler)() = appDelegate.sessionCompletionHandler; 
      appDelegate.sessionCompletionHandler = nil; 
      completionHandler(); 
     } 
     [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 
      [[NSNotificationCenter defaultCenter] postNotificationName:@"ContentRefreshNotification" object:Nil]; 
     }]; 
    } 
}]; 
} 

Quá trình qua lại này xảy ra trong trường hợp của tôi khi NSURLSession tồn tại trong một đối tượng là thuộc tính của ApplicationDelegate. Nếu bạn thực hiện NSURLSession là một thuộc tính của ApplicationDelegate thì tất cả mã này sẽ tồn tại trong cùng một tệp.

Hy vọng điều này sẽ hữu ích nhưng nếu bạn cần thêm thông tin, vui lòng xem hai hướng dẫn này 12 vì mã của tôi dựa trên những gì tôi đọc trong các tài liệu này.

+0

@Saddiq Jaffer Trong video NSURLSession trong WWDC 2014 lời khuyên của Apple về việc sử dụng từng tệp một và tải xuống toàn bộ tệp. – Sulabh

+0

Đó chính xác là những gì tôi đang làm trong phương thức '- (void) performBackgroundRefresh: (void (^) (UIBackgroundFetchResult)) completion'. Mã để tải xuống không được hiển thị trong ví dụ của tôi vì tôi chỉ đang cố gắng chứng minh cách xử lý và xử lý cuộc gọi hoàn thành. –

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