I using this code to create UICollectionViewCompositionalLayout
. Also I want to download file when user click on collection view cell. I use code in didSelectItemAt
to start downloading. But also I want to show progress in cell when file is downloading. I trying to use cellForItemAt
method to update progress view but this method not called. What method I need to use to update progress view every second?
<code>class StoreViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
var collectionView: UICollectionView!
var dataSource: UICollectionViewDiffableDataSource<Section, Item>?
let sections = Bundle.main.decode([Section].self, from: "section.json")
override func viewDidLoad() {
super.viewDidLoad()
createCollectionView()
collectionView.scrollToItem(at: IndexPath(item: 0, section: 0), at: .centeredHorizontally, animated: false)
}
func createDataSource() {
dataSource = UICollectionViewDiffableDataSource<Section, Item>(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<T: SelfConfiguringCell>(_ cellType: T.Type, with item: Item, for indexPath: IndexPath) -> T {
guard let cell = collectionView.dequeueReusableCell(
withReuseIdentifier: cellType.reuseIdentifier,
for: indexPath) as? T else {
fatalError("Unable to dequeue (cellType)")
}
cell.configure(with: item)
return cell
}
func reloadData() {
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections(sections)
for section in sections { snapshot.appendItems(section.item, toSection: section) }
dataSource?.apply(snapshot)
}
func createCollectionView() {
collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: createLayout())
collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
collectionView.isScrollEnabled = false
collectionView.delegate = self
collectionView.contentInsetAdjustmentBehavior = .never
view.addSubview(collectionView)
collectionView.register(SectionHeader.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: SectionHeader.reuseIdentifier)
collectionView.register(CarouselCell.self, forCellWithReuseIdentifier: CarouselCell.reuseIdentifier)
createDataSource()
reloadData()
}
func createCompositionalLayout() -> UICollectionViewLayout {
let layout = UICollectionViewCompositionalLayout { sectionIndex, layoutEnvironment in
let section = self.sections[sectionIndex]
switch section.identifier {
case "сarouselCell": return self.carouselSection(using: section)
default: return self.carouselSection(using: section)
}
}
return layout
}
func createLayout() -> UICollectionViewCompositionalLayout {
UICollectionViewCompositionalLayout {
(sectionIndex: Int, layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .fractionalHeight(1))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let interGroupSpacing = CGFloat(32)
let width = layoutEnvironment.container.contentSize.width * 1.05
let groupWidth = width / 3
let groupSize = NSCollectionLayoutSize(widthDimension: .absolute(groupWidth), heightDimension: .absolute(groupWidth))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
let section = NSCollectionLayoutSection(group: group)
let centerOffset = (layoutEnvironment.container.contentSize.height / 2) - (groupWidth / 2)
section.contentInsets = NSDirectionalEdgeInsets(top: centerOffset, leading: 0, bottom: 0, trailing: 0)
section.interGroupSpacing = interGroupSpacing * 2.0
section.orthogonalScrollingBehavior = .groupPagingCentered
section.contentInsetsReference = .none
section.visibleItemsInvalidationHandler = { (items, offset, environment) in
///` Настройка масштаба ячеек:
items.forEach { item in
let distanceFromCenter = abs((item.frame.midX - offset.x) - environment.container.contentSize.width / 2.0)
let minScale: CGFloat = 0.7
let maxScale: CGFloat = 1.1
let scale = max(maxScale - (distanceFromCenter / environment.container.contentSize.width), minScale)
item.transform = CGAffineTransform(scaleX: scale, y: scale)
}
}
return section
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if let cell = collectionView.cellForItem(at: indexPath) as? CarouselCell {
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let directory: String = path[0]
let fileManager = FileManager()
let destination = URL(fileURLWithPath: directory.appendingFormat("/(indexPath.row+1)/(indexPath.row+1).mp3"))
if fileManager.fileExists(atPath: destination.path){
self.navigationController?.pushViewController(SampleViewVC(), animated: true)
}else{
downloadQueue[indexPath.row+1]?.append(indexPath.row+1)
var queueArray = downloadQueue[indexPath.row+1] ?? [Int]()
queueArray.append(indexPath.row+1)
downloadQueue[indexPath.row+1] = queueArray
let url = URL(string: "(indexPath.row+1).mp3")!
let downloadManager = DownloadManager()
downloadManager.identifier = indexPath.row+1
downloadManager.tableId = indexPath.row+1
downloadManager.folderPath = "(indexPath.row+1)"
let downloadTaskLocal = downloadManager.activate().downloadTask(with: url)
downloadTaskLocal.resume()
downloadManager.onProgress = { (row, tableId, progress) in
print("downloadManager.onProgress:(row), (tableId), (String(format: "%.f%%", progress * 100))")
DispatchQueue.main.async {
if progress <= 1.0 {
cell.progressView.progress = progress
if progress == 1.0 {
} else {
cell.title.text = "(String(format: "%.f%%", progress * 100))"
}
}
}
}
}
}
}
}
</code>
<code>class StoreViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
var collectionView: UICollectionView!
var dataSource: UICollectionViewDiffableDataSource<Section, Item>?
let sections = Bundle.main.decode([Section].self, from: "section.json")
override func viewDidLoad() {
super.viewDidLoad()
createCollectionView()
collectionView.scrollToItem(at: IndexPath(item: 0, section: 0), at: .centeredHorizontally, animated: false)
}
func createDataSource() {
dataSource = UICollectionViewDiffableDataSource<Section, Item>(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<T: SelfConfiguringCell>(_ cellType: T.Type, with item: Item, for indexPath: IndexPath) -> T {
guard let cell = collectionView.dequeueReusableCell(
withReuseIdentifier: cellType.reuseIdentifier,
for: indexPath) as? T else {
fatalError("Unable to dequeue (cellType)")
}
cell.configure(with: item)
return cell
}
func reloadData() {
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections(sections)
for section in sections { snapshot.appendItems(section.item, toSection: section) }
dataSource?.apply(snapshot)
}
func createCollectionView() {
collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: createLayout())
collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
collectionView.isScrollEnabled = false
collectionView.delegate = self
collectionView.contentInsetAdjustmentBehavior = .never
view.addSubview(collectionView)
collectionView.register(SectionHeader.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: SectionHeader.reuseIdentifier)
collectionView.register(CarouselCell.self, forCellWithReuseIdentifier: CarouselCell.reuseIdentifier)
createDataSource()
reloadData()
}
func createCompositionalLayout() -> UICollectionViewLayout {
let layout = UICollectionViewCompositionalLayout { sectionIndex, layoutEnvironment in
let section = self.sections[sectionIndex]
switch section.identifier {
case "сarouselCell": return self.carouselSection(using: section)
default: return self.carouselSection(using: section)
}
}
return layout
}
func createLayout() -> UICollectionViewCompositionalLayout {
UICollectionViewCompositionalLayout {
(sectionIndex: Int, layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .fractionalHeight(1))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let interGroupSpacing = CGFloat(32)
let width = layoutEnvironment.container.contentSize.width * 1.05
let groupWidth = width / 3
let groupSize = NSCollectionLayoutSize(widthDimension: .absolute(groupWidth), heightDimension: .absolute(groupWidth))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
let section = NSCollectionLayoutSection(group: group)
let centerOffset = (layoutEnvironment.container.contentSize.height / 2) - (groupWidth / 2)
section.contentInsets = NSDirectionalEdgeInsets(top: centerOffset, leading: 0, bottom: 0, trailing: 0)
section.interGroupSpacing = interGroupSpacing * 2.0
section.orthogonalScrollingBehavior = .groupPagingCentered
section.contentInsetsReference = .none
section.visibleItemsInvalidationHandler = { (items, offset, environment) in
///` Настройка масштаба ячеек:
items.forEach { item in
let distanceFromCenter = abs((item.frame.midX - offset.x) - environment.container.contentSize.width / 2.0)
let minScale: CGFloat = 0.7
let maxScale: CGFloat = 1.1
let scale = max(maxScale - (distanceFromCenter / environment.container.contentSize.width), minScale)
item.transform = CGAffineTransform(scaleX: scale, y: scale)
}
}
return section
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if let cell = collectionView.cellForItem(at: indexPath) as? CarouselCell {
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let directory: String = path[0]
let fileManager = FileManager()
let destination = URL(fileURLWithPath: directory.appendingFormat("/(indexPath.row+1)/(indexPath.row+1).mp3"))
if fileManager.fileExists(atPath: destination.path){
self.navigationController?.pushViewController(SampleViewVC(), animated: true)
}else{
downloadQueue[indexPath.row+1]?.append(indexPath.row+1)
var queueArray = downloadQueue[indexPath.row+1] ?? [Int]()
queueArray.append(indexPath.row+1)
downloadQueue[indexPath.row+1] = queueArray
let url = URL(string: "(indexPath.row+1).mp3")!
let downloadManager = DownloadManager()
downloadManager.identifier = indexPath.row+1
downloadManager.tableId = indexPath.row+1
downloadManager.folderPath = "(indexPath.row+1)"
let downloadTaskLocal = downloadManager.activate().downloadTask(with: url)
downloadTaskLocal.resume()
downloadManager.onProgress = { (row, tableId, progress) in
print("downloadManager.onProgress:(row), (tableId), (String(format: "%.f%%", progress * 100))")
DispatchQueue.main.async {
if progress <= 1.0 {
cell.progressView.progress = progress
if progress == 1.0 {
} else {
cell.title.text = "(String(format: "%.f%%", progress * 100))"
}
}
}
}
}
}
}
}
</code>
class StoreViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
var collectionView: UICollectionView!
var dataSource: UICollectionViewDiffableDataSource<Section, Item>?
let sections = Bundle.main.decode([Section].self, from: "section.json")
override func viewDidLoad() {
super.viewDidLoad()
createCollectionView()
collectionView.scrollToItem(at: IndexPath(item: 0, section: 0), at: .centeredHorizontally, animated: false)
}
func createDataSource() {
dataSource = UICollectionViewDiffableDataSource<Section, Item>(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<T: SelfConfiguringCell>(_ cellType: T.Type, with item: Item, for indexPath: IndexPath) -> T {
guard let cell = collectionView.dequeueReusableCell(
withReuseIdentifier: cellType.reuseIdentifier,
for: indexPath) as? T else {
fatalError("Unable to dequeue (cellType)")
}
cell.configure(with: item)
return cell
}
func reloadData() {
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections(sections)
for section in sections { snapshot.appendItems(section.item, toSection: section) }
dataSource?.apply(snapshot)
}
func createCollectionView() {
collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: createLayout())
collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
collectionView.isScrollEnabled = false
collectionView.delegate = self
collectionView.contentInsetAdjustmentBehavior = .never
view.addSubview(collectionView)
collectionView.register(SectionHeader.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: SectionHeader.reuseIdentifier)
collectionView.register(CarouselCell.self, forCellWithReuseIdentifier: CarouselCell.reuseIdentifier)
createDataSource()
reloadData()
}
func createCompositionalLayout() -> UICollectionViewLayout {
let layout = UICollectionViewCompositionalLayout { sectionIndex, layoutEnvironment in
let section = self.sections[sectionIndex]
switch section.identifier {
case "сarouselCell": return self.carouselSection(using: section)
default: return self.carouselSection(using: section)
}
}
return layout
}
func createLayout() -> UICollectionViewCompositionalLayout {
UICollectionViewCompositionalLayout {
(sectionIndex: Int, layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .fractionalHeight(1))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let interGroupSpacing = CGFloat(32)
let width = layoutEnvironment.container.contentSize.width * 1.05
let groupWidth = width / 3
let groupSize = NSCollectionLayoutSize(widthDimension: .absolute(groupWidth), heightDimension: .absolute(groupWidth))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
let section = NSCollectionLayoutSection(group: group)
let centerOffset = (layoutEnvironment.container.contentSize.height / 2) - (groupWidth / 2)
section.contentInsets = NSDirectionalEdgeInsets(top: centerOffset, leading: 0, bottom: 0, trailing: 0)
section.interGroupSpacing = interGroupSpacing * 2.0
section.orthogonalScrollingBehavior = .groupPagingCentered
section.contentInsetsReference = .none
section.visibleItemsInvalidationHandler = { (items, offset, environment) in
///` Настройка масштаба ячеек:
items.forEach { item in
let distanceFromCenter = abs((item.frame.midX - offset.x) - environment.container.contentSize.width / 2.0)
let minScale: CGFloat = 0.7
let maxScale: CGFloat = 1.1
let scale = max(maxScale - (distanceFromCenter / environment.container.contentSize.width), minScale)
item.transform = CGAffineTransform(scaleX: scale, y: scale)
}
}
return section
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if let cell = collectionView.cellForItem(at: indexPath) as? CarouselCell {
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
let directory: String = path[0]
let fileManager = FileManager()
let destination = URL(fileURLWithPath: directory.appendingFormat("/(indexPath.row+1)/(indexPath.row+1).mp3"))
if fileManager.fileExists(atPath: destination.path){
self.navigationController?.pushViewController(SampleViewVC(), animated: true)
}else{
downloadQueue[indexPath.row+1]?.append(indexPath.row+1)
var queueArray = downloadQueue[indexPath.row+1] ?? [Int]()
queueArray.append(indexPath.row+1)
downloadQueue[indexPath.row+1] = queueArray
let url = URL(string: "(indexPath.row+1).mp3")!
let downloadManager = DownloadManager()
downloadManager.identifier = indexPath.row+1
downloadManager.tableId = indexPath.row+1
downloadManager.folderPath = "(indexPath.row+1)"
let downloadTaskLocal = downloadManager.activate().downloadTask(with: url)
downloadTaskLocal.resume()
downloadManager.onProgress = { (row, tableId, progress) in
print("downloadManager.onProgress:(row), (tableId), (String(format: "%.f%%", progress * 100))")
DispatchQueue.main.async {
if progress <= 1.0 {
cell.progressView.progress = progress
if progress == 1.0 {
} else {
cell.title.text = "(String(format: "%.f%%", progress * 100))"
}
}
}
}
}
}
}
}