- vừa được xem lúc

Download file từ cơ bản đến nâng cao trong iOS (phần 2)

0 0 17

Người đăng: Thanh Nguyen

Theo Viblo Asia

Introduction

Trong bài viết trước, chúng ta đã tìm hiểu về cách download file cơ bản nhất sử dụng URL Loading System.

Trong phần 2 này, hãy cùng nhau thử một kỹ thuật download nâng cao hơn một chút. Đó là cancel, pause và resume download. Trong nhiều trường hợp, app của bạn cần pause một task đang download dở và resume download đó trong tương lai.

Việc hỗ trợ pause và resume download sẽ giúp tiết kiệm thời gian và bandwidth mạng của user.

Ngoài ra, bạn có thể sử dụng kỹ thuật này để resume download file trong trường hợp quá trình download trước đó bị fail, ví dụ khi đang download thì bị mất mạng chẳng hạn.

Cancel download and store resume data

Để cancel một URLSessionDownloadTask, chúng ta có 2 cách:

  • Sử dụng method cancel(): đơn giản chỉ là cancel một download task mà không có thêm xử lý gì.
  • Sử dụng method cancel(byProducingResumeData:)

Trong method cancel(byProducingResumeData:), bạn có thể sử dụng một completion handler. Hệ thống sẽ call completion handler này sau khi download task được cancel. Handler này trả về một parameter resumeData, đây chính là data của file đang download dở. Nếu resumeData khác nil thì chúng ta có thể lưu lại data này và sử dụng nó để resume download trong tương lại. Ví dụ như đoạn code sau đây:

 @IBAction private func pauseDownloadButtonTapped(_ sender: Any) { currentDownloadTask.cancel { resumeDataOrNil in guard let resumeData = resumeDataOrNil else { // Download không thể resume, update lại UI nếu cần thiết print("Download can not resume") return } self.resumeData = resumeData DispatchQueue.main.async { self.messageLabel.text = "Download paused" } } }

Chú ý rằng, không phải download task nào cùng có thể resume. Một download chỉ có thể resume khi thỏa mãn các điều kiện sau:

  • File download gốc trên server không bị thay đổi trong suốt quá trình download, pause và resume.
  • Download task đó là một HTTP hoặc HTTPS GET request.
  • Server download trả về header field ETag hoặc Last-Modifierd hoặc cả hai trong response.
  • Server hỗ trợ các request download kiểu byte-range (download theo các khoảng đơn vị byte).
  • File download tạm dưới client không bị hệ thống xóa để giải phóng disk space.

Store resume data when download failed

Ngoài việc chủ động pause download rồi lưu lại resume data, chúng ta còn có thể resume download trong các trường hợp download fail do mất mạng, hoặc ra khỏi vùng phủ sóng wifi...

Khi download fail, session sẽ call delegate method urlSession(_:task:didCompleteWithError:).

Nếu như parameter error khác nil, hãy xem xem trong dictionary userInfo có chứa key NSURLSessionDownloadTaskResumeData hay không? Nếu như key này tồn tại thì chúng ta có thể resume bằng cách convert và lưu lại giá trị của key này thành resume data. Nếu như key không tồn tại thì có nghĩa là download task bị fail này sẽ không thể resume.

 func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { guard let error = error else { return } // Lấy ra userInfo của error let userInfo = (error as NSError).userInfo // Kiểm tra xem key NSURLSessionDownloadTaskResumeData có tồn tại hay không? // Nếu có thì convert value của nó sang kiểu Data và lưu lại resumeData if let resumeData = userInfo[NSURLSessionDownloadTaskResumeData] as? Data { self.resumeData = resumeData DispatchQueue.main.async { self.messageLabel.text = "Download paused" } } }

Resume download

Sau khi pause download do chủ quan hay khách quan, tại một thời điểm thích hợp, chúng ta có thể resume download bằng cách tạo một URLSessionDownloadTask bằng method [downloadTask(withResumeData:)] (https://developer.apple.com/documentation/foundation/urlsession/1409226-downloadtask) hoặc downloadTask(withResumeData:completionHandler:) từ URLSession. Sau đó truyền vào object resumeData mà chúng ta đã lưu trước đó.

 @IBAction private func resmeDownloadButtonTapped(_ sender: Any) { guard let resumeData = resumeData else { return } messageLabel.text = "Resuming download" let downloadTask = urlSession.downloadTask(withResumeData: resumeData) currentDownloadTask = downloadTask downloadTask.resume() }

Nếu resume download thành công, session sẽ call delegate method urlSession(_:downloadTask:didResumeAtOffset:expectedTotalBytes:).

Ở method này, chúng ta có thể dựa vào fileOffsetexpectedTotalBytes để tính toán và hiển thị thông tin, progress của download sau khi resume.

Kết quả:

Link project: https://github.com/oNguyenXuanThanh/DownloadTasks

Bình luận

Bài viết tương tự

- vừa được xem lúc

Học Flutter từ cơ bản đến nâng cao. Phần 1: Làm quen cô nàng Flutter

Lời mở đầu. Gần đây, Flutter nổi lên và được Google PR như một xu thế của lập trình di động vậy.

0 0 253

- vừa được xem lúc

Học Flutter từ cơ bản đến nâng cao. Phần 3: Lột trần cô nàng Flutter, BuildContext là gì?

Lời mở đầu. Màn làm quen cô nàng FLutter ở Phần 1 đã gieo rắc vào đầu chúng ta quá nhiều điều bí ẩn về nàng Flutter.

0 0 189

- vừa được xem lúc

Swift: Tạo custom phép toán tử (Operator) của riêng bạn!

Swift cho phép bạn tạo các toán tử có thể tùy chỉnh của riêng bạn. Điều này đặc biệt hữu ích khi bạn xử lý các loại dữ liệu của riêng mình. Operator Types in Swift. Có năm loại toán tử chính trong Swift.

0 0 45

- vừa được xem lúc

Chương 6 Protocol oriented programming.

Cuốn sách này là về lập trình hướng protocol. Khi Apple thông báo swift 2 ở WWDC 2015.

0 0 27

- vừa được xem lúc

Ví dụ về UIActivityViewController

Trên iOS, UIActivityViewController cung cấp giao diện thống nhất để người dùng chia sẻ và thực hiện các hành động trên văn bản, hình ảnh, URL và các mục khác trong ứng dụng. let string = "Hello, world!". let url = URL(string: "https://nshipster.com").

0 0 45

- vừa được xem lúc

Quản lý self và cancellable trong Combine.

. . Công việc quản lý bộ nhớ memory management thường trở nên phức tạp khi chúng ta thực hiện các tác vụ bất đồng bộ asynchronous vì chúng ta thường phải lưu giữ một số object nằm ngoài scope mà object được define trong khi vẫn phải đảm bảo được việc giải phóng object đó được thực hiện đúng quy trìn

0 0 28