У меня FirstTableViewContoller
с несколькими ячейками. Если я нажму на ячейку, я go до SecondTableViewContoller
с индикатором загрузки внутри ячеек. Когда я нажимаю на ячейку в SecondTableViewContoller
, мой индикатор запускается.
Также у меня есть класс DownloadManager
, который я могу начать загружать в firstTable
в SecondTableViewContoller
go до FirstTableViewContoller
, нажмите на вторую ячейку и от go до SecondTableViewContoller
с secondTable
. Тем самым я скачиваю файлы в два tableViews
.
Мой DownloadManager
класс работает нормально. И скачивание файлов. Но мои показатели прогресса иногда работают некорректно. Например, я начинаю скачивать файлы и go в другое приложение (Instagram, Facebook и др. c). После этого я возвращаюсь в своем приложении. Но мой прогресс ViewView не отображается (кроме загрузки файлов в это время). Когда я прячу и снова открываю свое приложение несколько раз, мои индикаторы отображаются и работают нормально. Пожалуйста, помогите мне исправить мои показатели. Я не понимаю, почему это происходит ...
SecondTableViewContoller
enum DownloadStatus {
case none
case inProgress
case completed
case failed
}
struct item {
var title : String!
let link = ""
var downloadStatus : DownloadStatus = .none
init(title: String) {
self.title = title
}
}
var downloadQ = [Int: [Int]]()
class SecondTableViewContoller: UITableViewController {
typealias ProgressHandler = (Int, Float) -> ()
var objects = [Any]()
var items = [item]()
var tableId = 0
var onProgress : ProgressHandler?
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: String(format: "cell", indexPath.row), for: indexPath) as! SecondViewCell
let cellFilePath = "\(indexPath.row).mp3"
let indexOfTask = allDownloadTasks.index { (task:URLSessionDownloadTask) -> Bool in
return task.currentRequest?.url?.lastPathComponent == cellFilePath
}
if indexOfTask == nil {
(cell.accessoryView as! FFCircularProgressView?)?.stopSpinProgressBackgroundLayer()
(cell.accessoryView as! FFCircularProgressView?)?.circularState = .completed
}
let item = items[indexPath.row]
cell.firstTextLabel.text = array[indexPath.row]
cell.secondTextLabel.text = item.title
let progressRing = FFCircularProgressView(frame: CGRect(x: CGFloat(0), y: CGFloat(0), width: CGFloat(24), height: CGFloat(24)))
if item.downloadStatus == .completed {
cell.tag = indexPath.row
cell.accessoryView = progressRing
progressRing.stopSpinProgressBackgroundLayer()
if let idx = downloadQ[self.buttonIndex]?.index(of: cell.tag) {
downloadQ[self.buttonIndex]?.remove(at: idx)
}
} else {
cell.accessoryView = nil
}
if let downloadQ = downloadQ[self.buttonIndex], downloadQ.contains(indexPath.row) {
cell.accessoryView = progressRing
progressRing.startSpinProgressBackgroundLayer()
}
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
var item = self.items[indexPath.row]
downloadQ[self.buttonIndex]?.append(indexPath.row)
var theArray = downloadQ[self.buttonIndex] ?? [Int]()
theArray.append(indexPath.row)
downloadQ[self.buttonIndex] = theArray
if downloadQ.isEmpty {
print("The downloadQ dictionary is empty.")
} else {
print("The downloadQ dictionary is not empty.")
}
let url = URL(string: "link.mp3")!
let downloadManager = DownloadManager()
downloadManager.identifier = indexPath.row
downloadManager.tableId = self.buttonIndex
downloadManager.folderPath = "\(self.id)"
let downloadTaskLocal = downloadManager.activate().downloadTask(with: url)
downloadTaskLocal.resume()
let circularProgressViewForCell = FFCircularProgressView(frame: CGRect(x: CGFloat(0), y: CGFloat(0), width: CGFloat(24), height: CGFloat(24)))
let cell = tableView.cellForRow(at: indexPath)
cell?.accessoryView = circularProgressViewForCell
circularProgressViewForCell.startSpinProgressBackgroundLayer()
downloadManager.onProgress = { (row, tableId, progress) in
DispatchQueue.main.async {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
if appDelegate.masterVC == nil {
print("master vc is nil")
return
}
if appDelegate.masterVC.tableId != tableId {
print("different table is nil")
return
}
let indexpath = IndexPath.init(row: row, section: 0)
let cell = appDelegate.masterVC.tableView.cellForRow(at: indexpath)
if progress <= 1.0 {
let progressRing = FFCircularProgressView(frame: CGRect(x: CGFloat(0), y: CGFloat(0), width: CGFloat(24), height: CGFloat(24)))
cell?.accessoryView = progressRing
progressRing.progress = CGFloat(progress)
if progress == 1.0 {
item.downloadStatus = .completed
progressRing.circularState = .completed
} else {
item.downloadStatus = .inProgress
}
}
}
}
}
DownloadManager
extension URLSession {
func getSessionDescription () -> Int {
// row id
return Int(self.sessionDescription!)!
}
func getDebugDescription () -> Int {
// table id
return Int(self.debugDescription)!
}
}
class DownloadManager : NSObject, URLSessionDelegate, URLSessionDownloadDelegate {
static var shared = DownloadManager()
var identifier : Int = -1
var tableId : Int = -1
var folderPath : String = ""
typealias ProgressHandler = (Int, Int, Float) -> ()
var onProgress : ProgressHandler? {
didSet {
if onProgress != nil {
let _ = activate()
}
}
}
override init() {
super.init()
}
func activate() -> URLSession {
let config = URLSessionConfiguration.background(withIdentifier: "\(Bundle.main.bundleIdentifier!).background.\(NSUUID.init())")
let urlSession = URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue())
urlSession.sessionDescription = String(identifier)
urlSession.accessibilityHint = String(tableId)
return urlSession
}
private func calculateProgress(session : URLSession, completionHandler : @escaping (Int, Int, Float) -> ()) {
session.getTasksWithCompletionHandler { (tasks, uploads, downloads) in
let progress = downloads.map({ (task) -> Float in
if task.countOfBytesExpectedToReceive > 0 {
return Float(task.countOfBytesReceived) / Float(task.countOfBytesExpectedToReceive)
} else {
return 0.0
}
})
let stringNumb = (session.accessibilityHint ?? "hit")
let someNumb = Int(stringNumb as String)
let string1 = (session.sessionDescription ?? "hit")
let some1 = Int(string1 as String)
if let idx = downloadQ[someNumb!]?.index(of: some1!) {
downloadQ[someNumb!]?.remove(at: idx)
print("remove:\(downloadQ)")
}
completionHandler(session.getSessionDescription(), Int(session.accessibilityHint!)!, progress.reduce(0.0, +))
}
}
func urlSession(_ session: URLSession,
downloadTask: URLSessionDownloadTask,
didFinishDownloadingTo location: URL){
let stringNumb = (session.accessibilityHint ?? "hit")
let someNumb = Int(stringNumb as String)
let string1 = (session.sessionDescription ?? "hit")
let some1 = Int(string1 as String)
if let idx = downloadQ[someNumb!]?.index(of: some1!) {
downloadQ[someNumb!]?.remove(at: idx)
print("remove:\(downloadQ)")
}
let fileName = downloadTask.originalRequest?.url?.lastPathComponent
let path = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
let documentDirectoryPath:String = path[0]
let fileManager = FileManager()
var destinationURLForFile = URL(fileURLWithPath: documentDirectoryPath.appending("/\(folderPath)"))
do {
try fileManager.createDirectory(at: destinationURLForFile, withIntermediateDirectories: true, attributes: nil)
destinationURLForFile.appendPathComponent(String(describing: fileName!))
try fileManager.moveItem(at: location, to: destinationURLForFile)
}catch(let error){
print(error)
}
}
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
let stringNumb = (session.accessibilityHint ?? "hit")
let someNumb = Int(stringNumb as String)
let string1 = (session.sessionDescription ?? "hit")
let some1 = Int(string1 as String)
if let idx = downloadQ[someNumb!]?.index(of: some1!) {
downloadQ[someNumb!]?.remove(at: idx)
print("remove:\(downloadQ)")
}
if totalBytesExpectedToWrite > 0 {
if let onProgress = onProgress {
calculateProgress(session: session, completionHandler: onProgress)
}
let progress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite)
}
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
let stringNumb = (session.accessibilityHint ?? "hit")
let someNumb = Int(stringNumb as String)
let string1 = (session.sessionDescription ?? "hit")
let some1 = Int(string1 as String)
if let idx = downloadQ[someNumb!]?.index(of: some1!) {
downloadQ[someNumb!]?.remove(at: idx)
print("remove:\(downloadQ)")
}
}
}