Как показать прогресс в элементе просмотра коллекции?IOS

Программируем под IOS
Ответить
Anonymous
 Как показать прогресс в элементе просмотра коллекции?

Сообщение Anonymous »

Я использую UICollectionViewCompositionalLayout с классом UICollectionViewCell. Также у меня есть класс DownloadManager. Я хочу загрузить файл после щелчка по ячейке. Я использую метод DidSelectItemAt, чтобы начать загрузку. И я использую ProgressView и title в классе UICollectionViewCell, чтобы показать состояние прогресса при начале загрузки. Но если я прокрутлю представление коллекции, когда мой файл находится в процессе загрузки, прогресс загрузки моей ячейки перепрыгнет и отобразится в другой ячейке, которая не загружается. Другими словами, ProgressView показывает прогресс в разных ячейках, но я загружаю только один файл. Как это исправить?
enum DownloadStatus {
case none
case inProgress
case completed
case failed
}

struct item {
var number: Int!
var downloadStatus: DownloadStatus = .none
init(number: Int) { self.number = number }
}

var downloadQueue = [Int: [Int]]()
var masterIndex = 0

extension URLSession {
func getSessionDescription () -> Int { return Int(self.sessionDescription!)! } // Item ID
func getDebugDescription () -> Int { return Int(self.debugDescription)! } // Collection 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() {
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(collectionId)
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
}
})
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 = downloadQueue[someNumb!]?.index(of: some1!) {
downloadQueue[someNumb!]?.remove(at: idx)
print("remove:\(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 {
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) {
if totalBytesExpectedToWrite > 0 {
if let onProgress = onProgress {
calculateProgress(session: session, completionHandler: onProgress)
}
}
}

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 = downloadQueue[someNumb!]?.index(of: some1!) {
downloadQueue[someNumb!]?.remove(at: idx)
print("remove:\(downloadQueue)")
}
}

}

UICollectionView
class CollectionController: UIViewController, UICollectionViewDelegate {

typealias ProgressHandler = (Int, Float) -> ()
var onProgress : ProgressHandler?
var items = [item]()

var collectionView: UICollectionView!
var dataSource: UICollectionViewDiffableDataSource?
let sections = Bundle.main.decode([Section].self, from: "carouselSection.json")

override func viewDidLoad() {
super.viewDidLoad()
createCollectionView()
setupScrollView()

let count = dataSource!.snapshot().numberOfItems
for index in 0...count {
items.append(item(number: index))
}
}

func setupScrollView() {
collectionView.scrollToItem(at: IndexPath(item: 0, section: 0), at: .centeredHorizontally, animated: false)
}

func createDataSource() {
dataSource = UICollectionViewDiffableDataSource(collectionView: collectionView) { collectionView, indexPath, item in
switch self.sections[indexPath.section].identifier {
case "carouselCell": return self.configure(CarouselCell.self, with: item, for: indexPath)
default: return self.configure(CarouselCell.self, with: item, for: indexPath)
}
}
}

func configure(_ cellType: T.Type, with item: Item, for indexPath: IndexPath) -> T {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellType.reuseIdentifier, for: indexPath) as? T else { fatalError(" — \(cellType)") }
cell.configure(with: item)
return cell
}

func reloadData() {
var snapshot = NSDiffableDataSourceSnapshot()
snapshot.appendSections(sections)
for section in sections { snapshot.appendItems(section.item, toSection: section) }
dataSource?.apply(snapshot)
}

func createCollectionView() {
collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: createCompositionalLayout())
collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
collectionView.isScrollEnabled = false
collectionView.delegate = self
collectionView.contentInsetAdjustmentBehavior = .never
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 item = 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 section = NSCollectionLayoutSection(group: group)
section.contentInsets = NSDirectionalEdgeInsets(top: (layoutEnvironment.container.contentSize.height/2) - (groupWidth/2), leading: 0, bottom: 0, trailing: 0)
section.orthogonalScrollingBehavior = .groupPagingCentered

return section
}
}

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let directory: String = path[0]
let fileManager = FileManager()
let destination = URL(fileURLWithPath: directory.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: "link")!
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 cell = self.collectionView.dequeueReusableCell(withReuseIdentifier: "carouselCell", for: indexPath) as! CarouselCell
cell = self.collectionView?.cellForItem(at: indexPath) as! CarouselCell

var item = items[indexPath.row]

downloadManager.onProgress = { (row, tableId, progress) in
print("downloadManager.onProgress:\(row), \(tableId), \(String(format: "%.f%%", progress * 100))")
DispatchQueue.main.async {
if progress

Подробнее здесь: https://stackoverflow.com/questions/791 ... -view-item
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «IOS»