dynamic image resizing after asynchronously downloading it from the firebase - ios

I am trying to dynamically adjust the image size depending upon the image that I download from the firebase database and present it in the table view cell. I want the width of the image to be the frame width and the height to adjust accordingly.
I have a customImageView class to download image asynchronously from firebase
I've tried many methods but in vain. Is there a super clean way to adjust the image size dynamically :-D
this Is my cell :
class viewControllerHomeCell: UITableViewCell {
#IBOutlet var mainImage: CstmImageView!
}
my cell for row at :
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellData = TableViewControllerHome.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! viewControllerHomeCell
cellData.mainImage.loadImagesWithUrl(from: self.postArray[indexPath.row].covrImgUrl)
}
and this is a UIImageView subclass to load images from the firebase async. :
class CstmImageView : UIImageView {
let imageCache = NSCache<AnyObject, AnyObject>()
var imageUrlString : String?
func loadImagesWithUrl(from imageUrl : String!) {
imageUrlString = imageUrl
self.image = nil
if let cachedImage = imageCache.object(forKey: imageUrl as AnyObject) as? UIImage {
self.image = cachedImage
return
}
let url = URLRequest(url: URL(string: imageUrl)!)
URLSession.shared.dataTask(with: url) { (data, response, eror) in
if eror != nil {
print(eror!)
return
}
DispatchQueue.main.async {
if let downloadedImage = UIImage(data : data!) {
if self.imageUrlString == imageUrl {
self.image = downloadedImage
}
self.imageCache.setObject(downloadedImage, forKey: imageUrl as AnyObject)
}
}
}.resume()
}
}
any help is appreciated a a lot : )

Take your imageView Height Outlet and connect with your imageView height constrain
class viewControllerHomeCell: UITableViewCell {
#IBOutlet var mainImage: UIImageView!
#IBOutlet var viewImageViewHeight: NSLayoutConstraint!
}
And Use Pod for Download Image
pod 'SDWebImage'
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cellData = TableViewControllerHome.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! viewControllerHomeCell
cellData.mainImage.sd_setImage(with:URL.init(string: "Pass Yor image Url string here"))
{ (image, error, imageCacheType, url) in
cellData.mainImage.image = image
viewImageViewHeight.constant = image?.size.height
}
cellData.mainImage.loadImagesWithUrl(from: self.postArray[indexPath.row].covrImgUrl)
}

Related

How to get different image from assets and assign it to image view in different table view cells

I am trying to add an image to my tableview cell by using an NFC reader session. So, my problem here is that every first reader session, I am getting the correct image in image view, but when I try the reader session the second time, I am stuck with two same last assigned image on both cells of my table view. I know it because of tableView.dequeueReusableCell method, but I am not sure which method to use to get correct image incorrect cells.
I have also attached a screenshot to make more clear of what I mean.
In the screenshot is should see an image of a water bottle from my assets, but instead, I am getting the last assigned image to every cell
Here is the code:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell", for: indexPath) as! TableViewCell
cell.nfcModel = arrData[indexPath.row]
// IMG CELL
cell.img.image = UIImage(named: name)
return cell
}
Not an expert in NFC readers.
1.Create an array of products to store product data from NFC render.
2.in tableView func cellForRowAt you can render the images from
favoriteMovies using displayMovieImage function.
Sidenote:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var favoriteMovies: [Movie] = []
override func viewWillAppear(_ animated: Bool) {
mainTableView.reloadData()
super.viewWillAppear(animated)
if favoriteMovies.count == 0 {
favoriteMovies.append(Movie(id: "tt0372784", title: "Batman Begins", year: "2005", imageUrl: "https://images-na.ssl-images-amazon.com/images/M/MV5BNTM3OTc0MzM2OV5BMl5BanBnXkFtZTYwNzUwMTI3._V1_SX300.jpg"))
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let moviecell = tableView.dequeueReusableCell(withIdentifier: "customcell", for: indexPath) as! CustomTableViewCell
let idx: Int = indexPath.row
moviecell.tag = idx
//title
moviecell.movieTitle?.text = favoriteMovies[idx].title
//year
moviecell.movieYear?.text = favoriteMovies[idx].year
// image
displayMovieImage(idx, moviecell: moviecell)
return moviecell
}
func displayMovieImage(_ row: Int, moviecell: CustomTableViewCell) {
let url: String = (URL(string: favoriteMovies[row].imageUrl)?.absoluteString)!
URLSession.shared.dataTask(with: URL(string: url)!, completionHandler: { (data, response, error) -> Void in
if error != nil {
print(error!)
return
}
DispatchQueue.main.async(execute: {
let image = UIImage(data: data!)
moviecell.movieImageView?.image = image
})
}).resume()
}

Could not cast value of type 'UITableViewCellContentView' (0x111d61280) to 'UIImageView' (0x111d4cdd0)

I'm new to Swift and I'm trying to build YouTube Video App.
I've got this error below.
[14835:1757198] Could not cast value of type 'UITableViewCellContentView' (0x111d61280) to 'UIImageView' (0x111d4cdd0).
And my code is below.
import UIKit
class tableview_blackpink: UIViewController , UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var videos:[Video] = [Video]()
override func viewDidLoad() {
super.viewDidLoad()
let model = VideoModel()
self.videos = model.getVideos()
self.tableView.dataSource = self
self.tableView.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return videos.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "BasicCell")!
//let videoTitle = videos[indexPath.row].videoTitle
//Customize the cell to display the video
//cell.textLabel?.text = videoTitle
//Construct the video thumbnail url
let videoThumbnailUrlString = "http://i1.ytimg.com/vi/" + videos[indexPath.row].videoId + "/mqdefault.jpg"
//Create NSURL object
let videoThumbnailUrl = URL(string: videoThumbnailUrlString)
if videoThumbnailUrl != nil{
//Create NSURL request object
let request = URLRequest(url: videoThumbnailUrl!)
//Create NSURLSession
let session = URLSession.shared
//Create datatask and pass in the request
let dataTask = session.dataTask(with: request, completionHandler: {(data: Data?, response: URLResponse?, error: Error?) -> Void in
DispatchQueue.main.async{
//Get a reference to the imageView element of the cell
let imageView = cell.contentView.viewWithTag(1) as! UIImageView
//Create an image object from the data and assign it into the imageView
imageView.image = UIImage(data: data!)
}
})
dataTask.resume()
}
return cell
}
}
And I got error here.
let imageView = cell.contentView.viewWithTag(1) as! UIImageView
I've googled considerable amount and the answer I got was fix this
let imageView = cell.viewWithTag(1) as! UIImageView
to
let imageView = cell.contentView.viewWithTag(1) as! UIImageView
I tried this but still got same error.
I'm following this YouTube video tutorial and code below doesn't work for latest Version.
Code for Swift2.2 is here
I appreciate any help. Thanks in advance.
imageView will be nil if it can't find a (tag == 1) that is also an UIImageView inside the cell's subviews.
let imageView = cell.subviews.first(where: { (temp) -> Bool in
return temp is UIImageView && temp.tag == 1
}) as? UIImageView

UIImageView in cell not showing image

So I have a table view and an array named offlineImages that contain images stored in the Documents folder. I want this images to show in the image view of the cells. The code compiles, but does not show the image. The URLs stored, the cell identifier and the tag are correct.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "offlineCell")
let mainImageView = cell?.viewWithTag(2) as! UIImageView
let mainImageURL = offlineImages[indexPath.row]
let mainImageData = NSData(contentsOf: mainImageURL)
let mainImage = UIImage(data: mainImageData! as Data)
mainImageView.image = mainImage
return cell!
}
Here is how I have downloaded the images:
let imageDestination: DownloadRequest.DownloadFileDestination = { _, _ in
var documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
documentsURL.appendPathComponent("image."+"png")
return (documentsURL, [.removePreviousFile])
}
Alamofire.download(mainImageURL, to: imageDestination).response { response in
if response.destinationURL != nil {
finalImageURL = response.destinationURL!
}
}
pbb you didn't save the pics correctly. Check that.
Solved it:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "offlineCell")
let mainImageView = cell?.viewWithTag(2) as! UIImageView
let mainImageURL = offlineImages[indexPath.row]
let mainImageData = NSData(contentsOf: mainImageURL)
let mainImage = UIImage(data: mainImageData! as Data)
if let image1 = mainImage {
mainImageView.image = image1
}
return cell!
}

How to load an image from URL and display it in tableView cell (Swift 3)

I have the image URL and I want to display that image in UIImageView which is placed in a tableView cell.
I created a custom cell and added an outlet for the imageView.
Since I am loading news the URL changes accordingly.
NOTE: I am using Alamofire to process my HTTP requests.
struct News {
let title: String
let text: String
let link: String
let imgUrl: String
init(dictionary: [String:String]) {
self.title = dictionary["title"] ?? ""
self.text = dictionary["text"] ?? ""
self.link = dictionary["link"] ?? ""
self.imgUrl = dictionary["imgUrl"] ?? ""
}
}
And loading info to my custom cell
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? newsCellTableViewCell
let news = newsData[indexPath.row]
cell?.headline.text = news.title
cell?.excerpt.text = news.text
cell?.thumbnailImage.text = news.imgUrl
return cell!
}
You can use this code to get image from url and can set a placeholder image as well. for example:-
cell.imageView?.imageFromURL(urlString: "urlString", PlaceHolderImage: UIImage.init(named: "imagename")!)
extension UIImageView {
public func imageFromServerURL(urlString: String, PlaceHolderImage:UIImage) {
if self.image == nil{
self.image = PlaceHolderImage
}
URLSession.shared.dataTask(with: NSURL(string: urlString)! as URL, completionHandler: { (data, response, error) -> Void in
if error != nil {
print(error ?? "No Error")
return
}
DispatchQueue.main.async(execute: { () -> Void in
let image = UIImage(data: data!)
self.image = image
})
}).resume()
}}
This becomes quite easy, as you're using Alamofire. Unlike #Mochi's example, this won't block the interface.
Here's an example:
Alamofire.request(news.imgUrl).response { response in
if let data = response.data {
let image = UIImage(data: data)
cell?.thumbnailImage.image = image
} else {
print("Data is nil. I don't know what to do :(")
}
}
*Please note I wasn't able to test this before I answered. You may need to tweak this code a bit.
I used a Kingfisher library
import Kingfisher
tableViewCell class:
class MyCell: UITableViewCell {
#IBOutlet weak var cellImg: UIImageView!
#IBOutlet weak var cellLbl: UILabel!
}
Assign this class to your cell in storyboard
And finally, do this in CellForRowAt
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell")! as! MyCell
let url = URL(string: "https://files.pitchbook.com/website/files/jpg/food_delivery_800.jpg")
cell.cellImg.kf.setImage(with: url)
return cell
}
That's it
Please Use SDWebImage. It's an imageview category that downloads the image in the background without freezing your UI, and also provides caching as well. You can set a placeholder image as well. Placeholders show until your actual image is downloaded. After downloading, the actual image in your cell's Imageview is updated automatically, and you don't need to use any completion handler.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? newsCellTableViewCell
let news = newsData[indexPath.row]
cell?.headline.text = news.title
cell?.excerpt.text = news.text
cell?.thumbnailImage.sd_setImageWithURL(NSURL(string: news.imgUrl), placeholderImage:UIImage(imageNamed:"placeholder.png"))
return cell!
}

How to call image urls and image view in cell for index path function for a collection view

I want to asynchronously dispatch 8 image urls in a collection view. I have created a class for collection view cell and also made an outlet to imageview in it. Now I want to configure the imageview from main view controller. Here is the code
let reuseIdentifier = "PhotosCollectionViewCell" // also enter this string as the cell identifier in the storyboard
var items = ["1", "2", "3", "4", "5", "6", "7", "8"]
// tell the collection view how many cells to make
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.items.count
}
// make a cell for each cell index path
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
// get a reference to our storyboard cell
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! PhotosCollectionViewCell
cell.imageView = imageView
return cell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
// handle tap events
print("You selected cell #\(indexPath.item)!")
}
func loadImage() {
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)) {
let urlString = "http://charcoaldesign.co.uk/AsyncImageView/Forest/IMG_0352.JPG"
let url = NSURL(string: urlString)
let data = NSData(contentsOfURL: url!)
dispatch_async(dispatch_get_main_queue(), {
self.imageView.image = UIImage(data: data!)
// self.items[0] = (data as? String)!
})
}
}
}
Here is a extension to make things more easy.
extension UIImageView {
func downloadImageFrom(link link:String, contentMode: UIViewContentMode) {
NSURLSession.sharedSession().dataTaskWithURL( NSURL(string:link)!, completionHandler: {
(data, response, error) -> Void in
dispatch_async(dispatch_get_main_queue()) {
self.contentMode = contentMode
if let data = data { self.image = UIImage(data: data) }
}
}).resume()
}
}
cell.imageView.downloadImageFrom(link: imageLinkArray[indexPath.row], contentMode: UIViewContentMode.ScaleAspectFit) //set your image from link array.
Also you can look below url for more help.
how to implement lazy loading of images in table view using swift
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
// get a reference to our storyboard cell
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! PhotosCollectionViewCell
cell.imageView = imageView
loadImage(imageView, urlPAssed: urlString)
return cell
}
func loadImage(imageViewObj : UIImageView , urlPAssed : NSString) {
//let urlString = "http://charcoaldesign.co.uk/AsyncImageView/Forest/IMG_0352.JPG"
let url = NSURL(string: urlPAssed as String)
NSURLSession.sharedSession().dataTaskWithURL(url!) { (data, response, error) in
if(error==nil)
{
dispatch_async(dispatch_get_main_queue(), { () -> Void in
imageViewObj.image = UIImage(data: data!)
})
}
else
{
imageViewObj.image = UIImage(named: "dummy")
}
}.resume()
}

Resources