I am utilizing this code to obtain my recordsdata and show progress in a my assortment view merchandise. But when I cover the app whereas some gadgets are downloading and after open app once more, the progress within the merchandise label will cease, nevertheless it will not cease downloading. replace the consumer interface after the my app opens once more?
import UIKit
enum DownloadStatus {
case none
case inProgress
case accomplished
case failed
}
struct merchandise {
var quantity: Int!
var downloadStatus: DownloadStatus = .none
var progress: Float = 0.0
init(quantity: Int) { self.quantity = quantity }
}
var downloadQueue = [Int: [Int]]()
var masterIndex = 0
extension URLSession {
func getSessionDescription () -> Int { return Int(self.sessionDescription!)! } // Merchandise ID
func getDebugDescription () -> Int { return Int(self.debugDescription)! } // Assortment ID
}
class DownloadManager : NSObject, URLSessionDelegate, URLSessionDownloadDelegate {
static var shared = DownloadManager()
var identifier : Int = -1
var collectionId : Int = -1
var folderPath : String = ""
typealias ProgressHandler = (Int, Int, Float) -> ()
var onProgress : ProgressHandler? {
didSet { if onProgress != nil { let _ = activate() } }
}
override init() {
tremendous.init()
}
func activate() -> URLSession {
let config = URLSessionConfiguration.background(withIdentifier: "(Bundle.principal.bundleIdentifier!).background.(NSUUID.init())")
let urlSession = URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue())
urlSession.sessionDescription = String(identifier)
urlSession.accessibilityHint = String(collectionId)
return urlSession
}
personal func calculateProgress(session : URLSession, completionHandler : @escaping (Int, Int, Float) -> ()) {
session.getTasksWithCompletionHandler { (duties, uploads, downloads) in
let progress = downloads.map({ (process) -> Float in
if process.countOfBytesExpectedToReceive > 0 {
return Float(process.countOfBytesReceived) / Float(process.countOfBytesExpectedToReceive)
} else {
return 0.0
}
})
completionHandler(session.getSessionDescription(), Int(session.accessibilityHint!)!, progress.scale back(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 = downloadQueue[someNumb!]?.firstIndex(of: some1!) {
downloadQueue[someNumb!]?.take away(at: idx)
print("take away:(downloadQueue)")
}
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 {
attempt fileManager.createDirectory(at: destinationURLForFile, withIntermediateDirectories: true, attributes: nil)
destinationURLForFile.appendPathComponent(String(describing: fileName!))
attempt fileManager.moveItem(at: location, to: destinationURLForFile)
} catch (let error) {
print(error)
}
}
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
if totalBytesExpectedToWrite > 0 {
if let onProgress = onProgress {
calculateProgress(session: session, completionHandler: onProgress)
}
}
}
func urlSession(_ session: URLSession, process: 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 = downloadQueue[someNumb!]?.firstIndex(of: some1!) {
downloadQueue[someNumb!]?.take away(at: idx)
print("take away:(downloadQueue)")
}
}
}
public struct Merchandise: Decodable, Hashable {
let index: Int
let title: String
let picture: String
let backgroundColor: String
let borderColor: String
}
public struct Part: Decodable, Hashable {
let index: Int
let identifier: String
let title: String
let subtitle: String
let merchandise: [Item]
}
class CollectionController: UIViewController, UICollectionViewDelegate {
typealias ProgressHandler = (Int, Float) -> ()
var onProgress : ProgressHandler?
var gadgets = [item]()
var collectionView: UICollectionView!
var dataSource: UICollectionViewDiffableDataSource?
let sections: [Section] = [.init(index: 0, identifier: "carouselCell", title: "title", subtitle: "sub", item: [
Item(index: 0, title: "Hello", image: "", backgroundColor: "", borderColor: ""),
Item(index: 1, title: "Hello", image: "", backgroundColor: "", borderColor: ""),
Item(index: 2, title: "Hello", image: "", backgroundColor: "", borderColor: ""),
Item(index: 3, title: "Hello", image: "", backgroundColor: "", borderColor: ""),
Item(index: 4, title: "Hello", image: "", backgroundColor: "", borderColor: ""),
Item(index: 5, title: "Hello", image: "", backgroundColor: "", borderColor: ""),
Item(index: 6, title: "Hello", image: "", backgroundColor: "", borderColor: ""),
Item(index: 7, title: "Hello", image: "", backgroundColor: "", borderColor: ""),
Item(index: 8, title: "Hello", image: "", backgroundColor: "", borderColor: ""),
Item(index: 9, title: "Hello", image: "", backgroundColor: "", borderColor: ""),
Item(index: 10, title: "Hello", image: "", backgroundColor: "", borderColor: ""),
Item(index: 11, title: "Hello", image: "", backgroundColor: "", borderColor: ""),
Item(index: 12, title: "Hello", image: "", backgroundColor: "", borderColor: "")
])]
override func viewDidLoad() {
tremendous.viewDidLoad()
createCollectionView()
setupScrollView()
let rely = dataSource!.snapshot().numberOfItems
for index in 0...rely {
gadgets.append(merchandise(quantity: index))
}
}
func setupScrollView() {
collectionView.collectionViewLayout = createCompositionalLayout()
collectionView.scrollToItem(at: IndexPath(merchandise: 0, part: 0), at: .centeredHorizontally, animated: false)
}
func createDataSource() {
dataSource = UICollectionViewDiffableDataSource(collectionView: collectionView) { [weak self] collectionView, indexPath, merchandise in
guard let self = self else { return UICollectionViewCell() }
swap self.sections[indexPath.section].identifier {
case "carouselCell":
let cell = self.configure(CarouselCell.self, with: merchandise, for: indexPath)
if indexPath.row < self.gadgets.rely { // <- replace UI base on self.gadgets
if self.gadgets[indexPath.row].state == .downloading {
cell.title.textual content = "(String(format: "%.f%%", self.gadgets[indexPath.row].progress * 100))"
}
}
return cell
default:
return self.configure(CarouselCell.self, with: merchandise, for: indexPath)
}
}
}
func configure(_ cellType: T.Kind, with merchandise: Merchandise, for indexPath: IndexPath) -> T {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellType.reuseIdentifier, for: indexPath) as? T else { fatalError(" — (cellType)") }
cell.configure(with: merchandise)
return cell
}
func reloadData() {
var snapshot = NSDiffableDataSourceSnapshot()
snapshot.appendSections(sections)
for part in sections { snapshot.appendItems(part.merchandise, toSection: part) }
dataSource?.apply(snapshot)
}
func createCollectionView() {
collectionView = UICollectionView(body: view.bounds, collectionViewLayout: createCompositionalLayout())
collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
collectionView.delegate = self
collectionView.contentInsetAdjustmentBehavior = .by no means
view.addSubview(collectionView)
collectionView.register(CarouselCell.self, forCellWithReuseIdentifier: CarouselCell.reuseIdentifier)
createDataSource()
reloadData()
}
func createCompositionalLayout() -> UICollectionViewLayout {
UICollectionViewCompositionalLayout { (sectionIndex: Int, layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .fractionalHeight(1))
let merchandise = NSCollectionLayoutItem(layoutSize: itemSize)
let groupWidth = (layoutEnvironment.container.contentSize.width * 1.05)/3
let groupSize = NSCollectionLayoutSize(widthDimension: .absolute(groupWidth), heightDimension: .absolute(groupWidth))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
let part = NSCollectionLayoutSection(group: group)
part.contentInsets = NSDirectionalEdgeInsets(prime: (layoutEnvironment.container.contentSize.peak/2) - (groupWidth/2), main: 0, backside: 0, trailing: 0)
part.interGroupSpacing = 20
part.orthogonalScrollingBehavior = .groupPagingCentered
return part
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let listing: String = path[0]
let fileManager = FileManager()
let vacation spot = URL(fileURLWithPath: listing.appendingFormat("/(indexPath.row+1)"))
var queueArray = downloadQueue[indexPath.row+1] ?? [Int]()
queueArray.append(indexPath.row+1)
downloadQueue[indexPath.row+1] = queueArray
let url = URL(string: "https://file-examples.com/storage/fe91352fe66730de9982024/2017/04/file_example_MP4_480_1_5MG.mp4")!
let downloadManager = DownloadManager()
downloadManager.identifier = indexPath.row+1
downloadManager.collectionId = indexPath.row+1
downloadManager.folderPath = "(indexPath.row+1)"
let downloadTaskLocal = downloadManager.activate().downloadTask(with: url)
downloadTaskLocal.resume()
//var merchandise = gadgets[indexPath.row] <- solely replace native worth
downloadManager.onProgress = { (row, tableId, progress) in
let row = row - 1
//print("downloadManager.onProgress:(row), (tableId), (String(format: "%.f%%", progress * 100))")
DispatchQueue.principal.async {
if progress <= 1.0 {
self.gadgets[row].progress = progress
if progress == 1.0 {
self.gadgets[row].downloadStatus = .accomplished
} else {
//cell.title.textual content = "(String(format: "%.f%%", progress * 100))"
self.gadgets[row].downloadStatus = .inProgress
}
self.reloadItem(indexPath: .init(row: row, part: 0))
}
}
}
}
func reloadItem(indexPath: IndexPath) {
guard let needReloadItem = dataSource!.itemIdentifier(for: indexPath) else { return }
var snapshot = NSDiffableDataSourceSnapshot()
snapshot.appendSections(sections)
for part in sections { snapshot.appendItems(part.merchandise, toSection: part) }
dataSource?.apply(snapshot)
snapshot.reloadItems([needReloadItem]) // <- reload gadgets
dataSource?.apply(snapshot, animatingDifferences: false)
}
}
protocol SelfConfiguringCell: UICollectionViewCell {
static var reuseIdentifier: String { get }
func configure(with: Merchandise)
}
class CarouselCell: UICollectionViewCell, SelfConfiguringCell {
static var reuseIdentifier: String { "carouselCell" }
let label = UILabel()
override init(body: CGRect) {
tremendous.init(body: body)
contentView.addSubview(label)
contentView.backgroundColor = .inexperienced
label.translatesAutoresizingMaskIntoConstraints = false
label.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
label.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
label.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
label.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
}
func configure(with merchandise: Merchandise) {
}
required init?(coder: NSCoder) {
fatalError("zzzzz")
}
}