what should I do to load asynchronous images in tableView? - swift

well, I should load images in the table view, I downloaded and loaded successful, but when I try to show in the table view, they doesn't appear, but, if I do scroll in the table view, the images will appear but the image won't in the middle of the cell.
I'm using swift 4.2
this lines helped me downloaded and loaded images
extension UIImageView {
func downloaded(from url: URL, contentMode mode: UIView.ContentMode = .scaleAspectFit) {
contentMode = mode
URLSession.shared.dataTask(with: url) { data, response, error in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil,
let image = UIImage(data: data)
else { return }
DispatchQueue.main.async() {
self.image = self.resizedImageWith(image: image, targetSize: CGSize(width: 100.0, height: 50.0))
}
}.resume()
}
func downloaded(from link: String, contentMode mode: UIView.ContentMode = .scaleAspectFit) {
guard let url = URL(string: link) else { return }
downloaded(from: url, contentMode: mode)
}
}
in my table view controller, I download the image with this function
func loadImages()
{
for img in arrFavServices
{
if let url = img?.logo
{
let imgDownload = UIImageView()
imgDownload.downloaded(from: url, contentMode: .redraw)
arrImages.append(imgDownload)
}
else
{
let imgDownload = UIImageView()
imgDownload.image = UIImage(named: "logo")
arrImages.append(imgDownload)
}
tableView.reloadData()
tableView.layoutIfNeeded()
tableView.layoutSubviews()
utilActivityIndicator.shared.hideLoader(view: view)
}
}
the array arrFavServices contains all the images' url, and arrImages has all the images previously downloaded. the function loadImages was called in the viewdidload.
and I use this function for show the images
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
if (arrFavServices[indexPath.section]?.logo) != nil
{
if arrImages[indexPath.section].image != nil
{
cell.imageView?.image = arrImages[indexPath.section].image
cell.imageView?.contentMode = .center
}
}
// Configure the cell...
if let color = arrFavServices[indexPath.section]?.color
{
cell.backgroundColor = UIColor(hexString: color)
}
return cell
}
what is my mistake? help meee please

I think you have 2 options
You download image async when cell visible ( I recommend )
Download all images and show cell visible
If you are download all images increase your memory usage of app and if too much usage it, iOS will crash your app.
First path:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
if let logo = arrFavServices[indexPath.section]?.logo {
// We need download image here
cell.imageView?.downloaded(from: logo, contentMode: .center)
}
// Configure the cell...
if let color = arrFavServices[indexPath.section]?.color {
cell.backgroundColor = UIColor(hexString: color)
}
return cell
}
Second Path:
You can use dispatch group. UITableView is waiting for download all images.
// Cache array
var downloadedImages: [UIImage] = []
// Create an instance
var dispatchGroup = DispatchGroup()
func loadImages() {
// Every tick of loop, we enter the group
for img in arrFavServices {
// Join the group
dispatchGroup.enter()
if let url = img?.logo {
let imgDownload = UIImageView()
imgDownload.downloaded(from: url, contentMode: .redraw, completion: { [weak self] downloadedImage in
guard let self = self else { return }
self.downloadedImages.append(downloadedImage)
// And leave group when task is done
dispatchGroup.leave()
})
} else {
let imgDownload = UIImageView()
imgDownload.image = UIImage(named: "logo")
arrImages.append(imgDownload)
// We can leave here too because we add image to array
dispatchGroup.leave()
}
}
// We have to listen group, and that we update tableView or UI todo
dispatchGroup.notify(queue: .main) {
self.tableView.reloadData()
self.tableView.layoutIfNeeded()
self.tableView.layoutSubviews()
self.utilActivityIndicator.shared.hideLoader(view: self.view)
}
}
You can set completion handler like below
extension UIImageView {
func downloaded(from url: URL, contentMode mode: UIView.ContentMode = .scaleAspectFit, completion: ((UIImage) -> Void)?) {
contentMode = mode
URLSession.shared.dataTask(with: url) { data, response, error in
guard
let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
let data = data, error == nil,
let image = UIImage(data: data)
else { return }
DispatchQueue.main.async() {
completion?(image)
}
}.resume()
}
func downloaded(from link: String, contentMode mode: UIView.ContentMode = .scaleAspectFit, completion: ((UIImage) -> Void)?) {
guard let url = URL(string: link) else { return }
downloaded(from: url, contentMode: mode, completion: completion)
}
}

Mate, why are you not using third party library?
Sd_webimage, Kingfisher you can just pod one of this library and in one line of code your image is visible at your desired index of tableview.

I will recommend using a Third-party library to load images in tableview.
add this in podfile.
pod 'SDWebImage'
add this simple code in cellForRowAtIndex
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if(indexPath.row > arrId.count-1){
// This will return an empty cell if all data is not downloaded and it will avoid the fatal error: index out of range
return UITableViewCell()
}
else{
let cell = tableView.dequeueReusableCell(withIdentifier: "AlbumCustomCell", for: indexPath) as! AlbumCustomCell
cell.lblId.text = String ( self.arrId[indexPath.row] )
cell.lblTitle.text = self.arrAlbumTitleString[indexPath.row]
cell.layer.shouldRasterize = true
cell.layer.rasterizationScale = UIScreen.main.scale
if let url = URL(string: self.arrAlbumThumbnailURLString[indexPath.row]) {
cell.albumThumbnaiilImage.sd_setImage(with: url, placeholderImage: UIImage(named: "placeholder"), options: .continueInBackground, context: nil)
}
return cell
}
}
This code is required to smoothly scroll the tableview.
cell.layer.shouldRasterize = true
cell.layer.rasterizationScale = UIScreen.main.scale
I am downloading 5000 images and showing them in the table view.
swift ios

Related

Adding image from api to CustomCell programmatically is getting laggy

My tableview gets slow when scrolling, I have a custom cell and a tableview:
I have this controller, where the api call is made and the array of trips is filled, then in cellForRowAt im creating the cell
class HistorialViewController: UIViewController , UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var historialTableView: UITableView!
var trips = [RootClass]()
override func viewDidLoad() {
super.viewDidLoad()
self.historialTableView.delegate = self
self.historialTableView.dataSource = self
self.historialTableView.register(CustomCellHistorial.self, forCellReuseIdentifier: cellId)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
print("coming back")
self.fetchTrips()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.historialTableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! CustomCellHistorial
let trip = self.trips[indexPath.row]
cell.trip = trip
return cell
}
private func fetchTrips(){
AFWrapper.getTripHistory( success: { (jsonResponse) in
self.trips = []
for item in jsonResponse["trips"].arrayValue {
self.trips.append(RootClass(fromJson:item))
}
self.reloadTrips()
Timer.scheduledTimer(withTimeInterval: 2.0, repeats: false) { (nil) in
self.indicator.stopAnimating()
}
}, failure: { (error) -> Void in
print(error)
})
}
func reloadTrips(){
DispatchQueue.main.async{
self.historialTableView.reloadData()
}
}
This is my CustomCell
class CustomCellHistorial : UITableViewCell{
var trip: RootClass? {
didSet{
dateTimeLabel.text = returnCleanDate(fecha: trip!.createdAt)
distanceAndTimeLabel.text = returnDistanceAndTime(distance: (trip?.trip!.real!.dist!)!, time: (trip?.trip!.real!.time)!)
priceLabel.text = returnCleanPrice(price: (trip?.trip!.real!.price!)!)
ratedLabel.text = "Not Rated"
self.productImage.image = self.returnDriverImage(photoUrl: (self.trip?.driver!.photo!)!)
if (trip!.score) != nil {
let score = trip!.score
if (score?.driver) != nil{
if(trip!.score!.driver!.stars! != 0.0 ){
ratedLabel.isHidden = true
}else{
ratedLabel.isHidden = false
}
}else{
print("yei")
}
}
}
}
private func returnDriverImage(photoUrl: String) -> UIImage{
let url = URL(string: photoUrl)
do {
let data = try Data(contentsOf: url!)
if let roundedimg = UIImage(data: data){
let croppedImageDriver = roundedimg.resize(toTargetSize: self.productImage.frame.size)
return croppedImageDriver
}
} catch let error {
debugPrint("ERRor :: \(error)")
let image = UIImage(named: "perfilIcono")
return image!
}
let image = UIImage(named: "perfilIcono")
return image!
}
Answers that I have found are for older versions of Swift, and the way they make the tableview its in storyboard or they are not handling custom cells.
I think the problem is in the returnDriverImage function.
This line
let data = try Data(contentsOf: url!)
You call from
self.productImage.image = self.returnDriverImage(photoUrl: (self.trip?.driver!.photo!)!)
blocks the main thread and re downloads the same image multiple times when scroll , please consider using SDWebImage

Reloading cells in view after image downloaded

I am currently learning swift. I have experience in android but now time for something new. I am starting with basics to load movie DB from API to table. I am storing dowloaded poster in Movie class (which also downloads them) when scrolling I can see the posters but after download the current cells in the view not updated, only after scroll. How can I implement callback from Movie to table view to update visible cells after download.
Movie:
import UIKit
let URL_PREFIX = "https://image.tmdb.org/t/p/original"
class Movie {
let movieId: CLong?
let title: String?
let posterPath: String?
let overview: String?
let releaseDate: String?
var posterImage: UIImage?
var callback: ((_ id: Int) -> Void)?
init(movieId: CLong,title: String,posterPath: String,overview: String,releaseDate: String,posterImage: UIImage?=nil) {
self.movieId = movieId
self.title = title
self.posterPath = posterPath
self.overview = overview
self.releaseDate = releaseDate
self.posterImage = posterImage
setResizedImage(path: posterPath)
}
func setResizedImage(path: String)
{
let conPath = URL_PREFIX + path
print("Path: \(conPath)")
guard let urlPath = URL(string: conPath) else {
print("You fucked up")
return
}
print("Download Started")
getData(from: urlPath) { data, response, error in
guard let _ = data, error == nil else { return }
print(response?.suggestedFilename ?? urlPath.lastPathComponent)
print("Download Finished")
//update
DispatchQueue.main.async()
{
self.posterImage = UIImage(data: data!)
}
}
}
}
MyViewController:
import UIKit
let URL_MOVIES = "https://api.themoviedb.org/3/movie/upcoming?
api_key=000";
class DataViewController: UIViewController,UITableViewDelegate,
UITableViewDataSource {
#IBOutlet weak var myTable: UITableView!
var movieArray :[Movie] = []
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return movieArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "MovieTableViewCell", for: indexPath) as? CustomTableViewCell else {
fatalError("The dequeued cell is not an instance of MovieTableViewCell.")
}
let movie = movieArray[indexPath.row]
cell.title.text = movie.title
cell.releaseDate.text = movie.releaseDate
cell.overview.text = movie.overview
//cell.url.text = movie.overview
if (movie.posterImage==nil)
{
print("Loaded placeholder")
cell.poster.image = UIImage(named: "poster")
}
else
{
print("Hello2")
cell.poster.image = movie.posterImage
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("You tapped cell number \(indexPath.row).")
}
override func viewDidLoad() {
super.viewDidLoad()
myTable.rowHeight = UITableView.automaticDimension
myTable.estimatedRowHeight = 50
getJsonFromUrl()
}
func getJsonFromUrl(){
let url = NSURL(string: URL_MOVIES)
URLSession.shared.dataTask(with: (url as URL?)!, completionHandler: {(data, response, error) -> Void in
if let jsonObj = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary {
if let resultArray = jsonObj.value(forKey: "results") as? NSArray
{
for film in resultArray
{
if let movieDict = film as? NSDictionary
{
//getting the name from the dictionary
let id = movieDict.value(forKey: "id")
let title = movieDict.value(forKey: "title")
let posterPath = movieDict.value(forKey: "poster_path")
let overview = movieDict.value(forKey: "overview")
let releaseDate = movieDict.value(forKey: "release_date")
let movie = Movie(movieId:id as! CLong, title: title as! String, posterPath: posterPath as! String, overview: overview as! String, releaseDate: releaseDate as! String)
self.movieArray.append(movie)
}
}
}
OperationQueue.main.addOperation({
self.myTable.reloadData()
})
}
}).resume()
}
}
You can add the download function inside the cell custom class and assign the imageView inside the callback, but this has many problems such as redownloading same image multiple times when scrolling, it's better to use SDWebImage or you can use Kingfisher Library
import SDWebImage
cell.poster.sd_setImage(with: URL(string:movie.imageUrlStr), placeholderImage: UIImage(named: "placeholder.png"))

Loading image from server in collection view

I have tried so many ways to load image from server in collection view, but the lag is still there when scrolling!
this is my ImageProvider class:
let imageCache = NSCache<AnyObject, AnyObject>()
class ImageProvider: UIImageView {
var imageUrl: String?
func loadImage(from urlString: String) {
self.imageUrl = urlString
let url = URL(string: urlString)!
image = nil
if let imageFromCache = imageCache.object(forKey: urlString as AnyObject) as? UIImage {
self.image = imageFromCache
return
}
URLSession.shared.dataTask(with: url) { (data, request, error) in
if error != nil {
print(error!)
return
}
DispatchQueue.main.async {
let imageToCache = UIImage(data: data!)
if self.imageUrl == urlString {
self.image = imageToCache
}
imageCache.setObject(imageToCache!, forKey: urlString as AnyObject)
}
}.resume()
}
}
setting up data:
func setupCVData(cell: TrackCell, item: Audio) {
cell.title.text = item.name
cell.url = URL(string: item.url!)!
if let url = cell.url {
var imageLink = String()
(_, _, imageLink) = fetcher.getData(from: url)
cell.imageUrl = imageLink
cell.updateImageView()
}
}
and updateImageView function:
func updateImageView() {
self.artwork.loadImage(from: imageUrl)
}
I've tried calling setupCVData in collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) and collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath)
I also used SDWebImage with no luck!
So what am I doing wrong here? I can't seem to figure out the problem.
As far as I know, you don't have to create the UIImage object on the main thread. I usually create UIImages in background threads without any problems. UI elements should only be modified on the main thread, however. So when you set the UIImageView's image property, make sure that's done on the main thread.
let imageToCache = UIImage(data: data!)
imageCache.setObject(imageToCache!, forKey: urlString as AnyObject)
DispatchQueue.main.async {
if self.imageUrl == urlString {
self.image = imageToCache
}
}

UICollectionView swift 3 laggy scroll UIImage

I am experiencing very choppy scrolling in my collection view. There are only 10 cells. It is because of my method of retrieving the images which is to take the URL and turn it to UIImage data.
Images variable is just an array of image URLs.
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return images.count
}
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "mediaCells", for: indexPath) as! MediaCell
let url = URL(string: images[indexPath.row] as! String)
let data = try? Data(contentsOf: url!)
cell.mediaImage.image = UIImage(data: data!)
return cell
}
A solution I found was to do this first for all images. The problem with this approach is that it will have to wait for all images to download the data and append to the array before we display the collectionView. This can take quite a few seconds 10-15 seconds before we can render the collection. Too slow!
override func viewDidLoad() {
super.viewDidLoad()
Alamofire.request(URL(string: "myURL")!,
method: .get)
.responseJSON(completionHandler: {(response) -> Void in
if let value = response.result.value{
let json = JSON(value).arrayValue
for item in json{
let url = URL(string: item["image"].string!)
let data = try? Data(contentsOf: url!)
self.images.append(data)
}
self.collectionView.reloadData()
}
})
}
Used SDWebImage from cocoapods to do Async image fetching.
https://cocoapods.org/?q=SDWebImage
cell.mediaImage.sd_setImage(with: URL(string: images[indexPath.row] as! String))
Some will shout about the use of globals, but this is the way I did previously:
Declare a global array of UIImage
var images: [UIImage] = []
When image is downloaded, append it to that array
for item in json{
let url = URL(string: item["image"].string!)
let data = try? Data(contentsOf: url!)
let image = UIImage(data: data!)
images.append(image)
NotificationCenter.default.post(Notification.Name(rawValue: "gotImage"), nil)
}
Follow the Notification in your VC
override function viewDidLoad() {
NotificationCenter.default.addObserver(self, selector: #selector(collectionView.reloadData()), name: NSNotification.Name(rawValue: "gotImage"), object: nil)
super.viewDidLoad()
}
Do not assign an image if not available in your cell for collectionView
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
.....
if let image = images[indexPath].row {
cell.mediaImage.image = image
}
....
}
PS: If all the downloading and loading action happens in the same VC, just declare images inside your VC class.
Seems like you need to do the lazy loading of images in your collection view based on the visible cells only. I have implemented the same approach like this.
1) First steps you need to create a class named it as PendingOperations.swift
class PendingOperations {
lazy var downloadsInProgress = [IndexPath: Operation]()
lazy var downloadQueue: OperationQueue = {
var queue = OperationQueue()
queue.name = "downloadQueue"
queue.maxConcurrentOperationCount = 1
return queue
}()
}
2) Seconds steps create a class named it as ImageDownloader where you can make your network call to download the image.
class ImageDownloader: Operation {
let imageId: String
init(imageId: String) {
self.imageId = imageId
}
override func main() {
if self.isCancelled {
return
}
Alamofire.request(URL(string: "myURL")!,
method: .get)
.responseJSON(completionHandler: {(response) -> Void in
if let value = response.result.value{
let json = JSON(value).arrayValue
for item in json{
let url = URL(string: item["image"].string!)
self.image = try? Data(contentsOf: url!)
})
if self.isCancelled {
return
}
}
}
3) Third steps implement some methods inside viewController to manipulate the operations based on the visible cells.
func startDownload(_ image: imageId, indexPath: IndexPath) {
if let _ = pendingOperations.downloadsInProgress[indexPath] {
return
}
let downloader = ImageDownloader(image: imageId)
downloader.completionBlock = {
if downloader.isCancelled {
return
}
}
pendingOperations.downloadsInProgress.removeValue(forKey: indexPath)
pendingOperations.downloadsInProgress[indexPath] = downloader
pendingOperations.downloadQueue.addOperation(downloader)
}
}
func suspendAllOperation() {
pendingOperations.downloadQueue.isSuspended = true
}
func resumeAllOperation() {
pendingOperations.downloadQueue.isSuspended = false
}
func loadImages() {
let pathArray = collectionView.indexPathsForVisibleItems
let allPendingOperations =
Set(Array(pendingOperations.downloadsInProgress.keys))
let visiblePath = Set(pathArray!)
var cancelOperation = allPendingOperations
cancelOperation.subtract(visiblePath)
var startOperation = visiblePath
startOperation.subtract(allPendingOperations)
for indexpath in cancelOperation {
if let pendingDownload =
pendingOperations.downloadsInProgress[indexpath] {
pendingDownload.cancel()
}
pendingOperations.downloadsInProgress.removeValue(forKey: indexpath)
}
for indexpath in startOperation {
let indexPath = indexpath
startDownload(imageId, indexPath: indexPath)
}
}
4) Fourth steps to implement the scrollView delegate methods.
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
suspendAllOperation()
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
loadImages()
resumeAllOperation()
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if !decelerate {
loadImages()
resumeAllOperation()
}
}
func clearImageDownloaderOperations() {
if pendingOperations.downloadsInProgress.count > 0 {
pendingOperations.downloadsInProgress.removeAll()
pendingOperations.downloadQueue.cancelAllOperations()
}
}
Using Kingfisher 5 for prefetching, loading, showing and caching images we can solve the issue.
let url = URL(fileURLWithPath: path)
let provider = LocalFileImageDataProvider(fileURL: url)
imageView.kf.setImage(with: provider)
https://github.com/onevcat/Kingfisher/wiki/Cheat-Sheet#image-from-local-file

Wrong indexPathForSelectedRow when using prepareForSegue

I'm trying to fill a tableView with some products from my MySQL database (using a PHP POST file) and at the moment everything is fine, but when I select a "Cell", the prepareForSegue is triggered, but the indexPathForSelectedRow is wrong, so it's showing a different product.
Here is my full code, I hope you can tell me something because I don't know why is this happening, I have tried a lot of things and I'm out of options...!
TableViewController.swift
import UIKit
class ListadoBuscarResultadosTableViewController: UITableViewController {
var option: String = ""
var productos = [Producto]()
var refreshControl2:UIRefreshControl!
var imageCache = [String:UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
requestPost()
title = self.option
tableView.allowsMultipleSelection = true
tableView.scrollsToTop = true
self.tableView.reloadData()
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.hidesBarsOnSwipe = false
self.navigationController?.setNavigationBarHidden(false, animated: true)
}
func refresh(sender:AnyObject) {
requestPost()
self.refreshControl2.endRefreshing()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// Return the number of sections.
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of rows in the section.
return productos.count
}
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
// Define the initial state (Before the animation)
cell.alpha = 0.25
// Define the final state (After the animation)
UIView.animateWithDuration(1.0, animations: { cell.alpha = 1 })
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// try to reuse cell
let cell = tableView.dequeueReusableCellWithIdentifier("Cell") as! BuscarCellTableViewCell
cell.selectionStyle = .None
//cell.nombre.text = productos[indexPath.row].nombre
//cell.marca.text = productos[indexPath.row].marca
//println(cell.nombre.text)
// get the deal image
let currentImage = productos[indexPath.row].imagen
let unwrappedImage = currentImage
var image = self.imageCache[unwrappedImage]
let imageUrl = NSURL(string: productos[indexPath.row].imagen)
// reset reused cell image to placeholder
cell.imagen.image = UIImage(named: "")
// async image
if image == nil {
let request: NSURLRequest = NSURLRequest(URL: imageUrl!)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: {(response: NSURLResponse!,data: NSData!,error: NSError!) -> Void in
if error == nil {
image = UIImage(data: data)
self.imageCache[unwrappedImage] = image
dispatch_async(dispatch_get_main_queue(), {
cell.imagen.image = image
cell.nombre.text = self.productos[indexPath.row].nombre
cell.marca.text = self.productos[indexPath.row].marca
})
}
else {
cell.nombre.text = self.productos[indexPath.row].nombre
cell.marca.text = self.productos[indexPath.row].marca
}
})
}
else {
cell.imagen.image = image
cell.nombre.text = self.productos[indexPath.row].nombre
cell.marca.text = self.productos[indexPath.row].marca
}
return cell
}
func requestPost () {
let request = NSMutableURLRequest(URL: NSURL(string: "http://www.web.es/productos_by_category.php")!)
request.HTTPMethod = "POST"
let postString = "category="+option
request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
data, response, error in
if error != nil {
//println("error=\(error)")
return
}
let responseString = NSString(data: data, encoding: NSUTF8StringEncoding)!
// JSON RESULTADO ENTERO
//println("responseString = \(responseString)")
self.productos = self.parseJsonData(data)
// Reload table view
dispatch_async(dispatch_get_main_queue(), {
self.tableView.reloadData()
})
}
task.resume()
}
func parseJsonData(data: NSData) -> [Producto] {
var productos = [Producto]()
var error:NSError?
let jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &error) as? NSDictionary
// Return nil if there is any error
if error != nil {
println(error?.localizedDescription)
}
// Parse JSON data
let jsonProductos = jsonResult?["lista_productos"] as! [AnyObject]
for jsonProducto in jsonProductos {
let producto = Producto()
producto.nombre = jsonProducto["nombre"] as! String
producto.imagen = jsonProducto["imagen"] as! String
producto.marca = jsonProducto["marca"] as! String
producto.distribuidor = jsonProducto["distribuidor"] as! String
producto.linea = jsonProducto["linea"] as! String
producto.precio = jsonProducto["precio"] as! String
productos.append(producto)
}
return productos
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "verProducto" {
if let indexPath = self.tableView.indexPathForSelectedRow() {
let destinationController = segue.destinationViewController as! MarcaProductoViewController
//println(productos[indexPath.row].nombre)
println(indexPath)
destinationController.nombre = productos[indexPath.row].nombre
}
}
}
Thanks in advance,
Regards.
try this way...
if segue.identifier == "verProducto"{
if let indexPath = tableView.indexPathForCell(sender as! BuscarCellTableViewCell){
var detailsVC = segue.destinationViewController as! MarcaProductoViewController
}
}