CollectionView return the same images twice - swift

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
}

Related

Swift How to move indexpath.item next index cell

I want to put all my photo albums in index 0 in the UICollectionViewCell and after another user album (index from 1) in the index cell, but I don't know how to do that. Below is the code I wrote. Please help me.
extension CollectionViewController : UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
userCollections = PHAssetCollection.fetchAssetCollections( with: .smartAlbum, subtype: .albumRegular, options: nil)
let numOfItem = userCollections.count
return numOfItem + 1
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as? CollectionViewCell else { return UICollectionViewCell()}
var coverAsset: PHAsset?
let collection = userCollections[indexPath.row]
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: true)]
if indexPath.item == 0 {
fetchReuslt = PHAsset.fetchAssets(with: fetchOptions)
coverAsset = fetchReuslt.firstObject
if let asset = coverAsset {
imgManger.requestImage(for: asset , targetSize: CGSize(width: cell.bounds.width , height: cell.bounds.height - 100), contentMode: .aspectFill, options: nil, resultHandler: { img, _ in
cell.collectionListCoverImg.image = img
})
}
cell.update(title: "All Photos", count: fetchReuslt.count)
} else {
let fetchedAssets = PHAsset.fetchAssets(in: collection, options: fetchOptions)
coverAsset = fetchedAssets.firstObject
if let asset = coverAsset {
imgManger.requestImage(for: asset , targetSize: CGSize(width: cell.bounds.width , height: cell.bounds.height - 50), contentMode: .aspectFill, options: nil, resultHandler: { img, _ in
cell.collectionListCoverImg.image = img
})
}
cell.update(title: collection.localizedTitle, count: fetchedAssets.count)
}
return cell
}

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.

swift UICollectionView similar preview and drag items

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)
}

How to send high quality images to another view using collectionview

My question is really simple. I have a collectionView and I'm sending image from it to another view and showing it. But the problem is that the quality is really bad. I made collectionView from photolibrary using tutorial from youtube. Here's my code how I'm sending image.
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let selectedCell = collectionView.cellForItem(at: indexPath) as! CollectionViewCell
ujaj = selectedCell.imageView.image
performSegue(withIdentifier: "segue077", sender: self)
}
And my full code:
import UIKit
import Photos
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
#IBOutlet public var bandau: UIImageView!
var imageArray = [UIImage]()
override func viewDidLoad() {
grabPhotos()
}
func grabPhotos(){
let imgManager = PHImageManager.default()
let requestOptions = PHImageRequestOptions()
requestOptions.isSynchronous = true
requestOptions.deliveryMode = .highQualityFormat // Quality of images
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
if let fetchResult : PHFetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions) {
if fetchResult.count > 0 {
for i in 0..<fetchResult.count {
imgManager.requestImage(for: fetchResult.object(at: i) as! PHAsset, targetSize: CGSize(width: 200, height: 200), contentMode: .aspectFill, options: requestOptions, resultHandler: {
image, error in
self.imageArray.append(image!)
})
}
}
else {
print("You got no photos")
//self.collectionView?.reloadData()
}
}
}
#IBOutlet weak var fakk: UIImageView!
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imageArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CollectionViewCell
let imageView = cell.viewWithTag(1) as! UIImageView
imageView.image = imageArray[indexPath.row]
return cell
}
public var ujaj: UIImage?
#IBAction func kadsasd(_ sender: Any) {
performSegue(withIdentifier: "segue077", sender: self)
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let selectedCell = collectionView.cellForItem(at: indexPath) as! CollectionViewCell
ujaj = selectedCell.imageView.image
performSegue(withIdentifier: "segue077", sender: self)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = collectionView.frame.width / 3 - 1
return CGSize(width: width, height: width)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 1.0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 1.0
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let main = segue.destination as! display
main.image = ujaj
}
Question is how to send FULL quality images? Because now I have 200x200 photos. If I change to higher then automatically my application crashes because of the memory. Maybe it's possible to get a full quality image when user clicks on the cell?
As long as you have your indexPath I suggest you to convert it to Integer and then ask for a photo from library once again. Don't forget to change .targetSize to PHImageManagerMaximumSize also .contentMode to PHImageContentMode.default
In your case:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let index : Int = indexPath.row
let imgManager = PHImageManager.default()
let requestOptions = PHImageRequestOptions()
requestOptions.isSynchronous = true
requestOptions.deliveryMode = .highQualityFormat // Quality of images
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
let fetchResult : PHFetchResult = PHAsset.fetchAssets(with: .image, options: fetchOptions)
imgManager.requestImage(for: fetchResult.object(at: index) , targetSize: PHImageManagerMaximumSize, contentMode: PHImageContentMode.default, options: requestOptions, resultHandler: {
image, error in
self.ujaj = image
})
performSegue(withIdentifier: "segue077", sender: self)
}

how to play video in swift 3 Xcode 8.2.1

I have displayed all local videos in Collection view as image.
but now when i click on cell it should play.
my code for displaying in collection view cell is given below
import UIKit
import Photos
import AVFoundation
import AVKit
class VideoViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
var imageArrray = [UIImage]()
// var playerController = AVPlayerViewController()
// var player:AVPlayer?
// var tempVideoFetchresult = PHFetchResult<AnyObject>()
override func viewDidLoad() {
//super.viewDidLoad()
grabVideos()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func grabVideos()
{
let imgManager = PHImageManager.default()
let requestOtions = PHImageRequestOptions()
requestOtions.isSynchronous = true
requestOtions.deliveryMode = .highQualityFormat
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
if let fetchResult : PHFetchResult = PHAsset.fetchAssets(with: .video, options: fetchOptions)
{
// tempVideoFetchresult = fetchResult as! PHFetchResult<AnyObject>
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: requestOtions, resultHandler: {
image, error in
self.imageArrray.append(image!)
})
}
}else{
print("You got no photos")
self.collectionView?.reloadData()
}
}
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imageArrray.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! videoCollectionViewCell
cell.videoImageView.image = imageArrray[indexPath.row]
//let imageView = cell.viewWithTag(1) as! UIImageView
// let imageView = cell.contentView.viewWithTag(1) as! UIImageView
// imageView.image = imageArrray[indexPath.row]
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = collectionView.frame.width/3 - 1
return CGSize(width: width, height: width)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 1.0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 1.0
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
//play video
// self.player = AVPlayer(playerItem: <#T##AVPlayerItem?#>)
}
}
i got answer
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let imgManager = PHImageManager.default()
let requestOtions = PHVideoRequestOptions()
requestOtions.deliveryMode = .highQualityFormat
imgManager.requestPlayerItem(forVideo: tempVideoFetchresult.object(at: indexPath.row) as! PHAsset, options: requestOtions, resultHandler: {
avplayeritem, error in
self.player = AVPlayer(playerItem: avplayeritem)
self.playerController.player = self.player
})
// self.player = AVPlayer(playerItem: <#T##AVPlayerItem?#>)
self.present(self.playerController,animated: true,completion: {
self.playerController.player?.play()
})
}