I'm currently learning iOS development and was wondering how I would go about passing a downloaded image to another view controller to be displayed there after tapping on a cell. So, a user would tap on a cell that has an image and then another view controller would pop up with that image. I downloaded the image using URLSession and then cached the image so that the user wouldn't have download the image every time they scroll back up or down to another cell that they've already seen. My issue now is how would I get that downloaded image to another view controller? I tried this, but videoController.thumbnailImageView.image is still coming back as nil.
let imageCache = NSCache<AnyObject, AnyObject>()
override func collectionView(_ collectionView: UICollectionView,
didSelectItemAt indexPath: IndexPath) {
let videoController = VideoController()
let videoUrl = URL(string: Videos[indexPath.item].thumbnail_image_name)
videoController.titleLabel.text = Videos[indexPath.item].title
videoController.thumbnailImageView.image = self.imageCache.object(forKey: videoUrl as AnyObject) as? UIImage
show(videoController, sender: Videos[indexPath.item])
}
Here is how I'm caching the images in cellForItemAt indexPath function.
DispatchQueue.main.async {
let imageToCache = UIImage(data: data!)
self.imageCache.setObject(imageToCache!, forKey: urlString as AnyObject)
cell.thumbnailImageView.image = UIImage(data: data!)
}
I figured it out. For anyone wondering you have to do this:
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at: indexPath) as! VideoCell
let videoController = VideoController()
videoController.titleLabel.text = Videos[indexPath.item].title
videoController.thumbnailImageView.image = cell.thumbnailImageView.image
show(videoController, sender: self)
}
You need to create the cell for the cell item at that selected Index path. I'm not sure why the cached way didn't work, but when I found out I will update this question for anyone else wondering.
Related
I am trying to populate my UICollectionView with my data from CoreData database. The problem is that I want to show a photo in Collection Cell and using data to create UIImage - this task can take a while. With the current solution the images are loaded approx. after 3 seconds but all the other data is already shown in collection view.
How should I add the loading overlay and know when all the images are ready to hide it, or what is correct approach?
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: viewModel.reuseIdentifier, for: indexPath) as? LocationCollectionViewCell {
cell.name.text = viewModel.locations[indexPath.row].name
cell.unlocked.text = viewModel.locations[indexPath.row].unlocked ? "Unlocked" : "Locked"
if let data = viewModel.locations[indexPath.row].image {
DispatchQueue.global(qos: .background).async {
let image = UIImage(data: data)
DispatchQueue.main.async {
cell.image.image = self.viewModel.locations[indexPath.row].unlocked ? image : image?.grayscale()
}
}
} else {
cell.image.image = viewModel.locations[indexPath.row].unlocked ? UIImage(named: "noun_Akropolis_403786") : UIImage(named: "noun_Akropolis_403786")?.grayscale()
}
return cell
} else {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: viewModel.reuseIdentifier, for: indexPath)
return cell
}
}
So #peter you can try follow things:
You can add loader in cell and show/hide it when image is nil or not.
For that create an array where when any image is loaded just append that index there. Until array doesnt contain all index show loader in screen else hide loader.
For handling error you can simply use try catch. If image is not loading or it is falied then you shouldn provide dummy or placeholder image. So that loader will be removed at one time.
I using a CollectionView with an ImageView in the prototype cell. I retrieve API result (title and image_url) and I would like to display an image and title in the collection view through array to retrieve the title and image_url.
Is it possible to retrieve image_url and display the image in the CollectionView?
I used SwiftyJSON to create the array and I can retrieve the API result (included title and image_url) in the array (can pint out the result). But I can't show it in the collection view.
I am posting an example code for your problem that might help you.
// Array that you retrieve from your API
let titleAndImageArray = []()
//CollectionView DataSourceMethod
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return titleAndImageArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell:YourCollectionViewCell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! YourCollectionViewCell
let labelTitle = titleAndImageArray[indexPath.row].title
let musicImageUrlString = titleAndImageArray[indexPath.row].image_url
cell.yourLabelOutletName.text = labelTitle
loadImage(indexPath: indexPath, cell: cell, urlString:musicImageUrlString)
}
*I have created a loadImage function to get image from URL which uses SDWebImage library which is Asynchronous image downloader SDWebImage *
func loadImage(indexPath:IndexPath,cell:YourCollectionViewCell,urlString:String){
cell.yourImageViewOutletName.sd_setImage(with: URL(string: urlString), placeholderImage: UIImage(named: "App-Default"),options: SDWebImageOptions(rawValue: 0), completed: { (image, error, cacheType, imageURL) in
})
}
I am loading videos in AVPlayer in collection view. Some cells repeat data. How to resolve this issue?
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell:homecollCell = self.collectionview.dequeueReusableCell(withReuseIdentifier: "homecollCell", for: indexPath) as! homecollCell
//cell.player?.pause()
let obj = self.friends_array[indexPath.row] as! Home
cell.img.sd_setImage(with: URL(string:self.appDelegate.imgbaseUrl!+obj.thum), placeholderImage: UIImage(named: ""))
let url = URL.init(string: self.appDelegate.imgbaseUrl!+obj.video_url)
let screenSize: CGRect = UIScreen.main.bounds
cell.playerItem = AVPlayerItem(url: url!)
//cell.player!.replaceCurrentItem(with: cell.playerItem)
cell.player = AVPlayer(playerItem: cell.playerItem!)
cell.playerLayer = AVPlayerLayer(player: cell.player!)
cell.playerLayer!.frame = CGRect(x:0,y:0,width:screenSize.width,height: screenSize.height)
cell.playerLayer!.videoGravity = AVLayerVideoGravity.resizeAspectFill
cell.playerView.layer.addSublayer(cell.playerLayer!)
cell.player?.play()
Cells are reusable so you have to remove or discard the changes what you have done on other cells using prepareForReuse(). Simply like this. Call this inside cell.
override func prepareForReuse() {
super.prepareForReuse()
self.label.text = nil
}
I am using a UIViewController with a UICollectionView to render a series of thumbnails to in the view.
When the user clicks the thumbnail it should bring them to a new scene that displays the full image.
I tried using didSelectItemAt to implement this but when testing it no output log is produced:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("Selecting item #\(indexPath.row)")
}
The thumbnail pictures are displayed properly with the following:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = imageCollection.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)as! ImageGalleryCell
if cellCount < imageArray.count{
print("Cell Count: ", cellCount)
let url = URL(string: "https://myurl.com\(imageArray[cellCount])")
print("url: ", url!)
cell.images.sd_setImage(with: url, placeholderImage: UIImage(named: "someImage"))
}
cellCount += 1
return cell
}
Is didSelectItemAt the proper method to use to click an thumbnail image and display a full image in a new view?
EDIT: I tried to use a segue as follows:
`override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "toFullImage"{
if let toFullImage = segue.destination as? ImagePageController{
toFullImage.fullImage = UIImage(named: fullImageArray[0])!
}
}
}`
But when I click on an image the app crashes and I get an error saying: Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
Is it possible to fix it so it can work with segue or is this completely wrong?
I'm working on UICollectionView. I'm assigning one image to collection view cell when user selects it, and changing the image when user selects other cell, as shown in below code
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath){
let selectedCell : CollectionCellForAlertView = collectionView.cellForItemAtIndexPath(indexPath) as! CollectionCellForAlertView
println("cell selected")
selectedCell.imageView.image = UIImage(named: "someImage.png")
}
func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath){
println("deselected")
let deselectedCell : CollectionCellForAlertView = collectionView.cellForItemAtIndexPath(indexPath) as! CollectionCellForAlertView
deselectedCell.imageView.image = UIImage(named: "someOtherImage.png")
}
Sometimes it works properly but some other times it crashes because 'deselectedCell' will have nil value. Can anybody please tel me how to resolve this.
I think this might work for you. I tested it in my app and it worked.
let deselectedCell = collectionView.cellForItemAtIndexPath(indexPath) as CollectionCellForAlertView
deselectedCell.imageView.image = UIImage(named: "someOtherImage.png")