Adding Youtube thumbnail on UICollectionView in swift - swift

I am trying to find a way to add a collection of youtube video thumbnails on a UICollectionView. But in the way how I am trying the thumbnail (image) is not being showed, and also I have not figure out a way to add a collection (array) of URL's on NSData.
Or if there are other ways to do so like with Youtube API.
And just to mention that I do not know Obj-C so any code in Obj-C wouldn't be very helpful.
Here is my code
var videoName:[String] = ["First Video", "Second Video", "Third Video"]
var videoImage:[String] = ["thumbnail1","thumbnail2","thumbnail3"]
let thumbnail1 = NSURL(string: "https://www.youtube.com/watch?v=sGF6bOi1NfA/0.jpg")
let thumbnail2 = NSURL(string: "https://www.youtube.com/watch?v=y71r1jhMdRk/0.jpg")
let thumbnail3 = NSURL(string: "https://www.youtube.com/watch?v=qfsRZsvraD8/0.jpg")
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell: SongCollectionView = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! SongCollectionView
cell.labelCell.text = videoName[indexPath.row]
let imageData = NSData(contentsOfURL: /*videoImage[indexPath.row]*/ thumbnail1!) // in the commented section I am trying to add an array of strings which contains thumbnail URL's
cell.imageCell.image = UIImage(data: imageData!)
return cell
}

A solution using tuplets rather than two separate arrays
let videoData = [("First Video", "sGF6bOi1NfA/0"), ("Second Video","y71r1jhMdRk/0"), ("Third Video", "qfsRZsvraD8/0")]
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell: SongCollectionView = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! SongCollectionView
let (name, token) = videoData[indexPath.row]
cell.labelCell.text = name
let imageData = NSData(contentsOfURL: NSURL(string: "https://www.youtube.com/watch?v=\(token).jpg")!)
cell.imageCell.image = UIImage(data: imageData)
return cell
}

Related

Load image from firebase database to cell imageview

I am very new to swift so am still following tutorials to learn how things work but things are not really working out for me like in the tutorial. Am trying to load image from firebase database into cell imageview like this
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
let userr = users[indexPath.row]
cell.textLabel?.text = userr.name
cell.detailTextLabel?.text = userr.email
if let profileImageUrl = userr.image_url {
let url = URL(string: profileImageUrl)
URLSession.shared.dataTask(with: url!, completionHandler: {(data, response, error) in
if error != nil {
print(error)
return
}
DispatchQueue.main.async {
cell.imageView?.image = UIImage(data: data!)
}
}).resume()
}
return cell
}
but it's not working, Both name and email both loads successful but image don't and i don't know where i am getting it wrong.

I am loading videos in AVPlayer in collection view but it repeats some cells data

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
}

How to pass json image data to collection view pinterest style in swift

Am developing a app using swift 2.2 in my app am using collection view with pinterest style so that am followed a method: https://github.com/chiahsien/CHTCollectionViewWaterfallLayout.
Am getting a data from the server which contains image that is
{"success":1,"error":0,"subcategory_value":"true","ad_count":126,"subcategory":[{"category id":"10","subcategory id":"37","subcategoryname":"Cars","image":"14720209352.jpg","link":"cars","id":"2628","advertising_id":"0002628","adtitle":"Toyota Corolla H5 1.8e make Year 2006 (petrol)","adtype":"1","specification":"","images":"toyota-corolla-h5-18e-make-year-2006-petrol-nm100370002628-14846608450.png,toyota-corolla-h5-18e-make-year-2006-petrol-nm100370002628-14846608461.png,toyota-corolla-h5-18e-make-year-2006-petrol-nm100370002628-14846608462.png,toyota-corolla-h5-18e-make-year-2006-petrol-nm100370002628-14846608463.png,toyota-corolla-h5-18e-make-year-2006-petrol-nm100370002628-14846608474.png","originalprice":"350000","offerprice":"0","contactno":"9840673154","address":"Tambaram, Chennai, Tamil Nadu, India","country":"India","state":"Tamil Nadu","districtname":"Chennai","postcode":"","subcategory_icon":"fa-id-badge"}]}
The key value :images" contains the image i want to pass that image to my collection view
code in my view controller:
import UIKit
import CHTCollectionViewWaterfallLayout
import SDWebImage
class ViewController: UIViewController,UICollectionViewDelegate,UICollectionViewDataSource,CHTCollectionViewDelegateWaterfallLayout,UITabBarDelegate,UISearchBarDelegate,UIToolbarDelegate {
var arrDict = NSMutableArray()
#IBOutlet var myCollectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
self.myCollectionView.dataSource = self
self.myCollectionView.delegate = self
setupCollectionView()
jsonParsingFromURL()
}
func setupCollectionView(){
// Create a waterfall layout
let layout = CHTCollectionViewWaterfallLayout()
// Change individual layout attributes for the spacing between cells
layout.minimumColumnSpacing = 4.0
layout.minimumInteritemSpacing = 4.0
// Collection view attributes
self.myCollectionView.autoresizingMask = [UIViewAutoresizing.FlexibleHeight, UIViewAutoresizing.FlexibleWidth]
self.myCollectionView.alwaysBounceVertical = true
self.myCollectionView.backgroundColor = UIColor.whiteColor()
// Add the waterfall layout to your collection view
self.myCollectionView.collectionViewLayout = layout
}
func jsonParsingFromURL () {
let url = NSURL(string: myapiKey + "category.com")
let request = NSURLRequest(URL: url!)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) {(response, data, error) in
self.startParsing(data!)
}
}
func startParsing(data :NSData)
{
let dict: NSDictionary!=(try! NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers)) as! NSDictionary
for i in 0 ..< (dict.valueForKey("subcategory") as! NSArray).count
{
arrDict.addObject((dict.valueForKey("subcategory") as! NSArray) .objectAtIndex(i))
}
myCollectionView.reloadData()
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("PinterestCell", forIndexPath: indexPath) as! MyCollectionViewCell
let URL_API_HOST2:String = "https://www.something.com/"
let images = arrDict[indexPath.row].valueForKey("images") as! NSString
let parts = images.componentsSeparatedByString(",")
let firstImage = parts[0]
cell.image.sd_setImageWithURL(NSURL(string: URL_API_HOST2 + (firstImage as String)))
return cell
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
}
help me to pass that image to the collection view

Async images change every time while scrolling?

So I'm creating an iOS app that lets you browse through the Unsplash wallpapers and I used UICollectionView to load the images in cells but whenever I scroll through an image, I go back the image changes into a different one.
Here's the code
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! ImageCollectionViewCell
let downloadQueue = dispatch_queue_create("com.donbytyqi.Papers", nil)
dispatch_async(downloadQueue) {
let imageURL = NSURL(string: "https://unsplash.it/200/300/?random")
let imageData = NSData(contentsOfURL: imageURL!)
var image: UIImage?
if imageData != nil {
image = UIImage(data: imageData!)
}
dispatch_async(dispatch_get_main_queue()) {
cell.imageView.image = image
}
}
return cell
}
EDIT: Two things going on:
collectionView.dequeueReusableCellWithReuseIdentifier reuses a cell that has already been created (if there's one available). So you're dequeueing one of your previous cells.
The URL your loading your images from generates a random image each time it is called.
Thus, when you scroll to the point where the first row of your collectionview is off screen, those cells get reused. Then when you scroll back up, the cells are recreated with a new random image from "https://unsplash.it/200/300/?random"
A way of circumventing this would be to keep an array of all your images indexed based on the cell index. Of course, if your images are very big and/or you have a really large collectionView, you may run out of memory.
Take a look at this code that I have mocked up. I have not verified that the code actually works.
//instance var to store your images
var imageArray: [UIImage]?
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! ImageCollectionViewCell
// Check if we have already loaded an image for this cell index
if let oldImage: UIImage = imageArray[indexPath.row] {
cell.imageView.image = oldImage
return cell
} else {
// remove the old image, before downloading the new one
cell.imageView.image = nil
}
let downloadQueue = dispatch_queue_create("com.donbytyqi.Papers", nil)
dispatch_async(downloadQueue) {
let imageURL = NSURL(string: "https://unsplash.it/200/300/?random")
let imageData = NSData(contentsOfURL: imageURL!)
var image: UIImage?
if imageData != nil {
image = UIImage(data: imageData!)
// Save image in array so we can access later
imageArray.insert(image, atIndex: indexPath.row)
}
dispatch_async(dispatch_get_main_queue()) {
cell.imageView.image = image
}
}
return cell
}
#toddg solution is correct. But still it have a problem in reusing the cell.
If the cell is reused before the network call completion then it will assign the downloaded image to another cell.
So I changed the code like following.
var imageArray: [UIImage]?
let downloadQueue = dispatch_queue_create("com.donbytyqi.Papers", nil)
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! ImageCollectionViewCell
if let oldImage: UIImage = imageArray[indexPath.row] {
cell.imageView.image = oldImage
return cell
} else {
cell.imageView.image = nil;
downloadImage(indexPath);
}
return cell
}
func downloadImage(indexPath: NSIndexPath) {
dispatch_async(downloadQueue) {
let imageURL = NSURL(string: "https://unsplash.it/200/300/?random")
let imageData = NSData(contentsOfURL: imageURL!)
var image: UIImage?
if imageData != nil {
image = UIImage(data: imageData!)
}
let cell = self.collectionView .cellForItemAtIndexPath(indexPath) as! ImageCollectionViewCell
dispatch_async(dispatch_get_main_queue()) {
cell.imageView.image = image
}
}
}
Hope this helps.
Let me explain what is going on actually.
When you scroll and go back you actually see the previously displayed cell with previously downloaded image (because of dequeueReusableCellWithReuseIdentifier:), and you will keep seeing that image until your new image will not downloaded, i.e. until execution of cell.imageView.image = image line.
So, you have to do following:
set cell.imageView.image = nil after dequeueReusableCellWithReuseIdentifier: line, like so:
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! ImageCollectionViewCell
cell.imageView.image = nil;
//...
This will remove previously downloaded image from imageView until new image download.
You should use something like SDWebImage or UIImageView+AFNetworking for async image downloading with cache support, because every time that your method is called the images will be downloaded again and again instead of getting cached image, and that is waste of traffic.
Good luck!

How to get the First Image from UICollectionViewCell and Save in UITableViewCell

I want to Save the First or the Last Image from the UICollectionView and Save it in the UITabelView Cell as UIImage.I try it with the first indexPath if indexPath == 0 catch the UIImage and then save it in CoreData as NSData but it doest works. Have anyone an idea how can i make that or gives another way to Display the UIImage in the UITableViewCell? Thanks for Help.
Here was the code from the UICollectionViewCell:
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("BookPicCell", forIndexPath: indexPath) as! BookPicCell
let cellcore = picture[indexPath.row]
cell.BookImage.image = UIImage(contentsOfFile: cellcore.foto!)
if indexPath.row == 0 {
let firstpic = cell.BookImage.image
let firstcell = UIImagePNGRepresentation(firstpic!)
let firstimag = NSEntityDescription.insertNewObjectForEntityForName("Book", inManagedObjectContext: self.mgdContext) as! Book
firstimag.firstimage = firstcell!
}
do {
try self.mgdContext.save()
} catch {
print("Error")
}
return cell
}
Here was the Code from the UITableViewCell:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let Cell = BookTableView.dequeueReusableCellWithIdentifier("BookCell", forIndexPath: indexPath) as! BookCell
let books = book[indexPath.row]
Cell.BookTitle.text = books.title
let picturecount = books.picture!.count
Cell.BookImageCount.text = "\(picturecount) Picture"
let firstpicture = books.firstimage!
Cell.BookImage.image = UIImage(data: firstpicture)
return Cell
}