swift UICollectionView similar preview and drag items - swift

I'm a new in swift and I'm developing UICollectionView drag and drop.
Now I have almost done but I stuck into a few issues.
I want to remove transparent Preview and remove cross button.
And make preview the same as draggable object.
What I want to get:
Here is my code:
func collectionView(_ collectionView: UICollectionView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
let photo = presenter.petPhotos[indexPath.row]
guard let cell = (collectionView.cellForItem(at: IndexPath(row: 2, section: 0)) as? PetPhotoCollectionViewCell) else {return []}
let cellSize = cell.mainImage.frame.size
guard let thumbnail = photo.path else {
return []
}
let itemProvider = NSItemProvider(object: photo.path! as NSString)
let dragItem = UIDragItem(itemProvider: itemProvider)
dragItem.localObject = photo
dragItem.previewProvider =
{ () -> UIDragPreview in
let image = UIImage(contentsOfFile: (URL(string: thumbnail)?.path)!)
let imageView = UIImageView(image: image)
imageView.bounds.size = cellSize
imageView.frame = imageView.contentClippingRect
imageView.cornerRadius = 9
imageView.layer.shadowColor = UIColor.black.cgColor
imageView.layer.shadowOffset = CGSize(width: 0, height: 2.0)
imageView.layer.shadowRadius = 3.0
imageView.layer.shadowOpacity = 0.5
imageView.layer.masksToBounds = true
imageView.layer.shadowPath = UIBezierPath(roundedRect: imageView.bounds, cornerRadius: imageView.layer.cornerRadius).cgPath
return UIDragPreview(view: imageView)
}
return [dragItem]
}
public func collectionView(_ collectionView: UICollectionView, dragPreviewParametersForItemAt indexPath: IndexPath) -> UIDragPreviewParameters? {
let cell = collectionView.cellForItem(at: IndexPath(row: 2, section: 0)) as? PetPhotoCollectionViewCell
let previewParameters = UIDragPreviewParameters()
previewParameters.visiblePath = UIBezierPath(roundedRect: (cell?.mainImage.frame)!, cornerRadius: 9)
return previewParameters
}
func collectionView(_ collectionView: UICollectionView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UICollectionViewDropProposal {
return UICollectionViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath)
}

Related

Why is the image quality so low? (swift)

I didn't like apples image picker so I decided to implement my own. I just finished the stage of getting all the users photos and displaying them in a collection view although I noticed that the difference in image quality is horrible. Here is my code:
import UIKit
import Photos
import PhotosUI
import Foundation
private let reuseIdentifier = "Cell"
var selectedImage = UIImage()
class CollectionVC: UICollectionViewController, UICollectionViewDelegateFlowLayout {
var imageArray = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
grapPhotos()
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imageArray.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath as IndexPath)
let imageView = cell.viewWithTag(1) as! UIImageView
cell.layer.cornerRadius = 4
imageView.image = imageArray[indexPath.row]
return cell
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let selectedImageName = imageArray[indexPath.item]
print(selectedImageName)
selectedImage = selectedImageName
performSegue(withIdentifier: "Custom", sender: self)
}
func grapPhotos() {
let imgManager = PHImageManager.default()
let requestOptions = PHImageRequestOptions()
requestOptions.isSynchronous = true
requestOptions.deliveryMode = .highQualityFormat
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
fetchOptions.predicate = NSPredicate(format: "mediaType = %d || mediaType = %d", PHAssetMediaType.image.rawValue, PHAssetMediaType.video.rawValue)
if let fetchResult : PHFetchResult = PHAsset.fetchAssets(with: fetchOptions) {
if fetchResult.count > 0 {
for i in 0..<fetchResult.count {
imgManager.requestImage(for: fetchResult.object(at: i), targetSize: CGSize(width: 200, height: 200), contentMode: .aspectFill, options: requestOptions, resultHandler: {
image, error in
self.imageArray.append(image!)
})
}
}
else {
self.collectionView?.reloadData()
print("No Photos")
}
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = collectionView.frame.width / 3 - 6
return CGSize(width: width, height: width)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 6.0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 6.0
}
}
I don't really know much about working with images so if anyone could help me out on displaying higher quality images that would be great.
This really works))
for index in 0..<fetchResult.count {
let asset = fetchResult.object(at: index) as PHAsset
let sizeFactor = UIScreen.main.scale
let deviceSize = UIScreen.main.nativeBounds.size
manager.requestImage(for: asset,
targetSize: CGSize(width: deviceSize.width * sizeFactor,
height: deviceSize.height * sizeFactor),
contentMode: .aspectFit,
options: requestOptions,
resultHandler: { (uiimage, info) in
if let image = uiimage {
allImages.append(image)
}
})
}
You only need to know ->
let sizeFactor = UIScreen.main.scale
let deviceSize = UIScreen.main.nativeBounds.size
Image quality depends on the phone your viewing on - retina screens require more pixels. You'll need to multiply your targetSize by UIScreen.main.scale.
Try setting targetSize: CGSize(width: 200 * UIScreen.main.scale, height: 200.0 * UIScreen.main.scale) in your imgManager.requestImage function.
For Retina displays, the scale factor may be 3.0 or 2.0 and one point can represented by nine or four pixels, respectively. For standard-resolution displays, the scale factor is 1.0 and one point equals one pixel.

Collection view with dynamic cell sizes glitches on drag and drop

I have a CollectionView where all of my cells are aligned to the center of the view, utilising a custom flow layout. Here is the code for the collectionViewController:
let columnLayout = FlowLayout(
minimumInteritemSpacing: 10,
minimumLineSpacing: 10,
sectionInset: UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
)
var dataSource: [String] = ["USA", "Brazil", "China","Really long long long", "Unite Kingdom", "Japan", "Mexico", "India", "Really long long", "Short", "USA", "Brazil", "China","Really long long long", "Unite Kingdom", "Japan", "Mexico", "India", "Really long long"]
override func viewDidLoad() {
super.viewDidLoad()
collectionView.collectionViewLayout = columnLayout
collectionView.contentInsetAdjustmentBehavior = .always
collectionView.register(TestCell.self, forCellWithReuseIdentifier: "Cell")
collectionView.dragInteractionEnabled = true
collectionView.dragDelegate = self
collectionView.dropDelegate = self
collectionView.delegate = self
collectionView.dataSource = self
}
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return dataSource.count
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// dataArary is the managing array for your UICollectionView.
let item: String = dataSource[indexPath.row]
return CGSize(width: item.widthOfString(usingFont: .systemFont(ofSize: 16)) + 25, height: 40)
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as? TestCell
cell?.textLabel.text = dataSource[indexPath.row]
return cell!
}
fileprivate func reorderItems(coordinator: UICollectionViewDropCoordinator, destinationIndexPath: IndexPath, collectionView: UICollectionView) {
if let item = coordinator.items.first,
let sourceIndexPath = item.sourceIndexPath {
collectionView.performBatchUpdates ({
self.dataSource.remove(at: sourceIndexPath.item)
self.dataSource.insert(item.dragItem.localObject as! String, at: destinationIndexPath.item)
collectionView.deleteItems(at: [sourceIndexPath])
collectionView.insertItems(at: [destinationIndexPath])
}, completion: nil)
collectionView.reloadData()
coordinator.drop(item.dragItem, toItemAt: destinationIndexPath)
}
Code for the FlowLayout Class:
class FlowLayout: UICollectionViewFlowLayout {
required init(minimumInteritemSpacing: CGFloat = 0, minimumLineSpacing: CGFloat = 0, sectionInset: UIEdgeInsets = .zero) {
super.init()
estimatedItemSize = UICollectionViewFlowLayout.automaticSize
self.minimumInteritemSpacing = minimumInteritemSpacing
self.minimumLineSpacing = minimumLineSpacing
self.sectionInset = sectionInset
sectionInsetReference = .fromSafeArea
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
let layoutAttributes = super.layoutAttributesForElements(in: rect)!.map { $0.copy() as! UICollectionViewLayoutAttributes }
guard scrollDirection == .vertical else { return layoutAttributes }
// Filter attributes to compute only cell attributes
let cellAttributes = layoutAttributes.filter({ $0.representedElementCategory == .cell })
// Group cell attributes by row (cells with same vertical center) and loop on those groups
for (_, attributes) in Dictionary(grouping: cellAttributes, by: { ($0.center.y / 10).rounded(.up) * 10 }) {
// Get the total width of the cells on the same row
let cellsTotalWidth = attributes.reduce(CGFloat(0)) { (partialWidth, attribute) -> CGFloat in
partialWidth + attribute.size.width
}
// Calculate the initial left inset
let totalInset = collectionView!.safeAreaLayoutGuide.layoutFrame.width - cellsTotalWidth - sectionInset.left - sectionInset.right - minimumInteritemSpacing * CGFloat(attributes.count - 1)
var leftInset = (totalInset / 2 * 10).rounded(.down) / 10 + sectionInset.left
// Loop on cells to adjust each cell's origin and prepare leftInset for the next cell
for attribute in attributes {
attribute.frame.origin.x = leftInset
leftInset = attribute.frame.maxX + minimumInteritemSpacing
}
}
return layoutAttributes
}
}
I then added a UICollectionViewDragDelegate and a UICollectionViewDropDelegate extensions in order to enable the user to reorder the cells. The two extensions:
extension CollectionViewController: UICollectionViewDragDelegate {
func collectionView(_ collectionView: UICollectionView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
let item = self.dataSource[indexPath.row]
let itemProvider = NSItemProvider(object: item as NSString)
let dragItem = UIDragItem(itemProvider: itemProvider)
dragItem.localObject = item
return [dragItem]
}
}
extension CollectionViewController: UICollectionViewDropDelegate {
func collectionView(_ collectionView: UICollectionView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UICollectionViewDropProposal {
if collectionView.hasActiveDrag {
return UICollectionViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath)
}
return UICollectionViewDropProposal(operation: .forbidden)
}
func collectionView(_ collectionView: UICollectionView, performDropWith coordinator: UICollectionViewDropCoordinator) {
var destinationindexPath: IndexPath
if let indexPath = coordinator.destinationIndexPath {
destinationindexPath = indexPath
} else {
let row = collectionView.numberOfItems(inSection: 0)
destinationindexPath = IndexPath(item: row - 1, section: 0)
}
if coordinator.proposal.operation == .move {
self.reorderItems(coordinator: coordinator, destinationIndexPath: destinationindexPath, collectionView: collectionView)
}
}
}
For some strange reason the cells glitch out in the app when reordering them:
https://imgur.com/dmEQLqh
Thanks for the help

Custom Drag&Drop UICollectionViewLayout snap to a grid

I am working on a App where I can keep track of my substitutions of my youth soccer team.
Following a tutorial by Payal Gupta on drag & drop into collections & tables I managed to get a drag and drop between two collection views (PlayersOntoTheField and Substitutes) working Screenshot.
When I drag a substitute player into my playground it should now snap to the predefined team line-up (e.g. 3-2-1 in the screenshot). Is it possible to get such behavior with a custom UICollectionViewLayout or does anyone have another suggestion?
Thank you you very much in advance for any help.
Danny
//Based on a work by:
//Payal Gupta (https://github.com/pgpt10/DragAndDrop-CollectionView)
import UIKit
class ViewController: UIViewController
{
private var substitutes = ["player1", "player2", "player3", "player4"]
private var players = [String]()
#IBOutlet weak var substitutesCollectionView: UICollectionView!
#IBOutlet weak var playersCollectionView: UICollectionView!
override func viewDidLoad()
{
super.viewDidLoad()
//SubstitutesCollectionView drag and drop configuration
self.substitutesCollectionView.dragInteractionEnabled = true
self.substitutesCollectionView.dragDelegate = self
self.substitutesCollectionView.dropDelegate = self
//PlayersCollectionView drag and drop configuration
self.playersCollectionView.dragInteractionEnabled = true
self.playersCollectionView.dropDelegate = self
self.playersCollectionView.dragDelegate = self
self.playersCollectionView.reorderingCadence = .fast //default value - .immediate
}
//MARK: Private Methods
private func reorderItems(coordinator: UICollectionViewDropCoordinator, destinationIndexPath: IndexPath, collectionView: UICollectionView)
{
let items = coordinator.items
if items.count == 1, let item = items.first, let sourceIndexPath = item.sourceIndexPath
{
var dIndexPath = destinationIndexPath
if dIndexPath.row >= collectionView.numberOfItems(inSection: 0)
{
dIndexPath.row = collectionView.numberOfItems(inSection: 0) - 1
}
collectionView.performBatchUpdates({
if collectionView === self.playersCollectionView
{
self.players.remove(at: sourceIndexPath.row)
self.players.insert(item.dragItem.localObject as! String, at: dIndexPath.row)
}
else
{
self.substitutes.remove(at: sourceIndexPath.row)
self.substitutes.insert(item.dragItem.localObject as! String, at: dIndexPath.row)
}
collectionView.deleteItems(at: [sourceIndexPath])
collectionView.insertItems(at: [dIndexPath])
})
coordinator.drop(items.first!.dragItem, toItemAt: dIndexPath)
}
}
private func copyItems(coordinator: UICollectionViewDropCoordinator, destinationIndexPath: IndexPath, collectionView: UICollectionView)
{
collectionView.performBatchUpdates({
var indexPaths = [IndexPath]()
for (index, item) in coordinator.items.enumerated()
{
let indexPath = IndexPath(row: destinationIndexPath.row + index, section: destinationIndexPath.section)
if collectionView === self.playersCollectionView
{
self.players.insert(item.dragItem.localObject as! String, at: indexPath.row)
}
else
{
self.substitutes.insert(item.dragItem.localObject as! String, at: indexPath.row)
}
indexPaths.append(indexPath)
}
collectionView.insertItems(at: indexPaths)
})
}
}
// MARK: - UICollectionViewDataSource Methods
extension ViewController : UICollectionViewDataSource
{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return collectionView == self.substitutesCollectionView ? self.substitutes.count : self.players.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
if collectionView == self.substitutesCollectionView
{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell1", for: indexPath) as! MyCollectionViewCell
cell.customImageView?.image = UIImage(named: self.substitutes[indexPath.row])
cell.customLabel.text = self.substitutes[indexPath.row].capitalized
return cell
}
else
{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell2", for: indexPath) as! MyCollectionViewCell
cell.customImageView?.image = UIImage(named: self.players[indexPath.row])
cell.customLabel.text = self.players[indexPath.row].capitalized
return cell
}
}
}
// MARK: - UICollectionViewDragDelegate Methods
extension ViewController : UICollectionViewDragDelegate
{
func collectionView(_ collectionView: UICollectionView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem]
{
let item = collectionView == substitutesCollectionView ? self.substitutes[indexPath.row] : self.players[indexPath.row]
let itemProvider = NSItemProvider(object: item as NSString)
let dragItem = UIDragItem(itemProvider: itemProvider)
dragItem.localObject = item
return [dragItem]
}
func collectionView(_ collectionView: UICollectionView, itemsForAddingTo session: UIDragSession, at indexPath: IndexPath, point: CGPoint) -> [UIDragItem]
{
let item = collectionView == substitutesCollectionView ? self.substitutes[indexPath.row] : self.players[indexPath.row]
let itemProvider = NSItemProvider(object: item as NSString)
let dragItem = UIDragItem(itemProvider: itemProvider)
dragItem.localObject = item
return [dragItem]
}
func collectionView(_ collectionView: UICollectionView, dragPreviewParametersForItemAt indexPath: IndexPath) -> UIDragPreviewParameters?
{
if collectionView == substitutesCollectionView
{
let previewParameters = UIDragPreviewParameters()
previewParameters.visiblePath = UIBezierPath(rect: CGRect(x: 15, y: 5, width: 30, height: 30))
return previewParameters
}
return nil
}
}
// MARK: - UICollectionViewDropDelegate Methods
extension ViewController : UICollectionViewDropDelegate
{
func collectionView(_ collectionView: UICollectionView, canHandle session: UIDropSession) -> Bool
{
return session.canLoadObjects(ofClass: NSString.self)
}
func collectionView(_ collectionView: UICollectionView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UICollectionViewDropProposal
{
if collectionView === self.substitutesCollectionView
{
if collectionView.hasActiveDrag
{
return UICollectionViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath)
}
else
{
return UICollectionViewDropProposal(operation: .forbidden)
}
}
else
{
if collectionView.hasActiveDrag
{
return UICollectionViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath)
}
else
{
return UICollectionViewDropProposal(operation: .copy, intent: .insertAtDestinationIndexPath)
}
}
}
func collectionView(_ collectionView: UICollectionView, performDropWith coordinator: UICollectionViewDropCoordinator)
{
let destinationIndexPath: IndexPath
if let indexPath = coordinator.destinationIndexPath
{
destinationIndexPath = indexPath
}
else
{
// Get last index path of table view.
let section = collectionView.numberOfSections - 1
let row = collectionView.numberOfItems(inSection: section)
destinationIndexPath = IndexPath(row: row, section: section)
}
switch coordinator.proposal.operation
{
case .move:
self.reorderItems(coordinator: coordinator, destinationIndexPath:destinationIndexPath, collectionView: collectionView)
break
case .copy:
self.copyItems(coordinator: coordinator, destinationIndexPath: destinationIndexPath, collectionView: collectionView)
default:
return
}
}
}
That my workaround for custom UICollectionViewLayout so far:
import UIKit
class LineUp_3_2_1View: UICollectionViewLayout {
private var center: CGPoint!
private var itemSize: CGSize!
private var radiusOfCircleViews: CGFloat!
private var numberOfItems: Int!
override func prepare() {
super.prepare()
guard let collectionView = collectionView else { return }
radiusOfCircleViews = CGFloat(30.0)
itemSize = CGSize(width: radiusOfCircleViews * 2, height: radiusOfCircleViews * 2)
center = CGPoint(x: collectionView.bounds.midX, y: collectionView.bounds.midY)
numberOfItems = collectionView.numberOfItems(inSection: 0)
}
override var collectionViewContentSize: CGSize {
return collectionView!.bounds.size
}
override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
if (indexPath.item == 0) {attributes.center = CGPoint(x: 169, y: 344)}
if (indexPath.item == 1) {attributes.center = CGPoint(x: 46, y: 250)}
if (indexPath.item == 2) {attributes.center = CGPoint(x: 169, y: 250)}
if (indexPath.item == 3) {attributes.center = CGPoint(x: 287, y: 250)}
if (indexPath.item == 4) {attributes.center = CGPoint(x: 80, y: 156)}
if (indexPath.item == 5) {attributes.center = CGPoint(x: 253, y: 156)}
if (indexPath.item == 6) {attributes.center = CGPoint(x: 169, y: 62)}
attributes.size = itemSize
return attributes
}
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
return (0 ..< collectionView!.numberOfItems(inSection: 0))
.flatMap { item -> UICollectionViewLayoutAttributes? in // `compactMap` in Xcode 9.3
self.layoutAttributesForItem(at: IndexPath(item: item, section: 0))
}
}
}

Reusing cells with hidden / scaled components

I reuse collection view cell as a custom radio button. As a radio button selection I use two views:
border view
mark view
Mark view is hidden and scaled. It is basically simple selection.
In RadioButtonCollectionViewCell :
var checkMark: UIView = {
let view = UIView()
view.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)
view.backgroundColor = .darkGreyFts
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
override var isSelected: Bool {
get {
return super.isSelected
} set {
super.isSelected = newValue
isSelected ? checkMark.scaleAnimate(1) : checkMark.scaleAnimate(-1)
}
}
override func prepareForReuse() {
super.prepareForReuse()
self.infoLabel.text = nil
self.checkMark.isHidden = false
}
UIView extension :
func scaleAnimate(_ state: Int) {
switch state {
case 1:
self.isHidden = false
UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseOut, animations: {
self.transform = CGAffineTransform(scaleX: 1, y: 1)
})
case -1:
UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseOut, animations: {
self.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)
}, completion: { _ in
self.isHidden = true
})
default:
break
}
}
// MARK: - UICollectionView delegate.
extension DriverFormsViewController : UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if let cell = collectionView.cellForItem(at: indexPath) as? RadioButtonCollectionViewCell {
cell.isSelected = true
collectionCellSelectedAtIndexPath = indexPath
}
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
if let cell = collectionView.cellForItem(at: indexPath) as? RadioButtonCollectionViewCell {
cell.isSelected = false
}
}
}
// MARK: - UICollectionView data source.
extension DriverFormsViewController : UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return optionsDictionary.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath) as! RadioButtonCollectionViewCell
let key = optionsKeys[indexPath.row]
cell.infoLabel.text = optionsDictionary[key]
cell.checkMark.isHidden = true
if let collectionCellIsSelectedAtIndexPath = collectionCellSelectedAtIndexPath {
if collectionCellIsSelectedAtIndexPath == indexPath {
cell.checkMark.scaleAnimate(1)
}
}
return cell
}
}
How I would be able to reuse view which is hidden/not scaled/not ? Whenever I scroll down and back to the collection selected cell is not selected - mean, check mark is hidden and whenever I click on this cell it goes without animations. Any ideas what might be wrong ?
Thanks in advance!
You have to make sure to deselect the current cell before selecting a new one
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if let currentSelectedIndexPath = collectionCellSelectedAtIndexPath,
let currentCell = cellForItem(at: currentSelectedIndexPath) as? RadioButtonCollectionViewCell {
currentCell.isSelected = false
}
if let cell = collectionView.cellForItem(at: indexPath) as? RadioButtonCollectionViewCell {
cell.isSelected = true
collectionCellSelectedAtIndexPath = indexPath
}
}
And instead of using prepareForReuse I would add an else clause in cellForItemAt
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath) as! RadioButtonCollectionViewCell
let key = optionsKeys[indexPath.row]
cell.infoLabel.text = optionsDictionary[key]
cell.checkMark.isHidden = true
if let collectionCellIsSelectedAtIndexPath = collectionCellSelectedAtIndexPath,
collectionCellIsSelectedAtIndexPath == indexPath {
cell.checkMark.scaleAnimate(1)
} else {
cell.checkMark.scaleAnimate(-1)
}
return cell
}

CollectionView return the same images twice

When I request the images and load them to my collection View, the request return low resolution images and high resolution images at the same time.
As you can see the same images are returned twice with low and hight resolution in my collectionView.
Code:
var imageArray = [UIImage]()
let imgManager = PHImageManager.default()
override func viewDidLoad() {
super.viewDidLoad()
collectionView.delegate = self
collectionView.dataSource = self
grabPhoto()
}
func grabPhoto(){
let imageSize = CGSize(width: 800, height: 800)
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
if let fetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions) as? PHFetchResult {
if fetchResult.count > 0 {
for i in 0..<fetchResult.count {
imgManager.requestImage(for: fetchResult.object(at: i), targetSize: imageSize, contentMode: .aspectFill , options: nil, resultHandler: { (image, error) in
self.imageArray.append(image!)
self.photoImageView.image = self.imageArray.first
self.collectionView.reloadData()
print("Result Size Is \(image?.size)")
})
}
}
} else {
print("you got no Photos!")
}
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imageArray.count
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "UploadPhotoCell", for: indexPath)
let imageView = cell.viewWithTag(1) as! UIImageView
imageView.image = imageArray[indexPath.row]
return cell
}