2

I have tried several different approaches and nothing has yet to work. I am pulling in album artwork for a recently played tableview for my radio station app. I get blank images when there is no album artwork to pull into the cell. I just want to have my station logo "WhiteLogo.png" as a placeholder whenever there is no album artwork pulled into the tableview cell. Any help in the right direction is much appreciated. Thanks

import UIKit

//----------
//MARK: JSON
//----------

//The Initial Response From The JSON
struct Response: Codable {

    var playHistory: Album

}

//The Album Received Which Is An Array Of Song Data
struct Album: Codable {
    var song: [SongData]

}

//The SongData From The PlayHistory Album
struct SongData: Codable{

    var album: String
    var artist: String
    var cover: String
    var duration: String
    var programStartTS: String
    var title: String
}


class TableViewController: UITableViewController {

    //1. Create An Array To Store The SongData
    var songs = [SongData]()
    var currentStation: RadioStation!
    var downloadTask: URLSessionDownloadTask?

    override func viewDidLoad() { super.viewDidLoad()


        self.tableView.delegate = self
        self.tableView.dataSource = self

        //2. Load The JSON From The Main Bundle

        guard let urlText = URL (string: "http://streamdb3web.securenetsystems.net/player_status_update/JACKSON1_history.txt")
            else { return }


        do{
            //a. Get The Data From The From The File
            let data = try Data(contentsOf: urlText)

            //b. Decode The Data To Our Structs
            let albumData = try JSONDecoder().decode(Response.self, from: data)

            //c. Append The Songs Array With The PlayHistory
            albumData.playHistory.song.forEach { songs.append($0) }

            //d. Test Some Data
            print("""
                **The First Album Details**
                Album = \(songs[0].album)
                Artist = \(songs[0].artist)
                Cover = \(songs[0].cover)
                Duration = \(songs[0].duration)
                Start = \(songs[0].programStartTS)
                Title = \(songs[0].title)
                """)

            //3. Load The Data
            DispatchQueue.main.async {
                self.tableView.reloadData()
            }
        }catch{

            print(error)
        }

    }

    //-----------------
    //MARK: UITableView
    //-----------------


    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return songs.count
    }


    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {


        //1. Create A Cell
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell

        //2. Set It's Text
        cell.songTitle.text = songs[indexPath.row].title
        cell.artistLabel.text = songs[indexPath.row].artist

        //3. Get The Image
        if let imageURL = URL(string: songs[indexPath.row].cover){

            let request = URLSession.shared.dataTask(with: imageURL) { (imageData, response, error) in

                if let error = error{

                    print(error)

                }else{

                    guard let image = imageData else { return }

                    DispatchQueue.main.async {
                        cell.songCover.image = UIImage(data: image)
                        cell.setNeedsLayout()
                        cell.layoutIfNeeded()
                    }

                }
            }


            request.resume()
        }

        return cell

    }


    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        print("""
            **Album \(indexPath.row) Selected**
            Album = \(songs[indexPath.row].album)
            Artist = \(songs[indexPath.row].artist)
            Cover = \(songs[indexPath.row].cover)
            Duration = \(songs[indexPath.row].duration)
            Start = \(songs[indexPath.row].programStartTS)
            Title = \(songs[indexPath.row].title)
            """)
    }

}
Manuel Duarte
  • 165
  • 12
  • See https://stackoverflow.com/questions/46199203/downloading-uiimage-via-alamofireimage/46199246#46199246 – Salman Ghumsani Apr 04 '18 at 05:31
  • Place the `placeholder image` to your `imageview` before downloading the image from server. After getting a success set the downloaded image to your `imageview`, and if you do not get any images from server, keep the `placeholder` to your `imageview`. – iPeter Apr 04 '18 at 05:34
  • @iPeter How do I go about doing that? I'm a newb. – Manuel Duarte Apr 04 '18 at 05:58

4 Answers4

2

Just the right case handling is required.
I would set the placeholder image first and then proceed to download an image from a URL.

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    //...

    /*
     Start with placeholder image so it shows until the image  download completes.
     And if the next `if let imageURL` condition fails, the placeholder image will stay
     */
    cell.songCover.image = UIImage(named: "WhiteLogo")

    //Continue with your logic, no change really but could be shortened to:
    if let imageURL = URL(string: songs[indexPath.row].cover) {
        let request = URLSession.shared.dataTask(with: imageURL) { (imageData, response, error) in
            guard let imageData = imageData else { return }

            DispatchQueue.main.async {
                cell.songCover.image = UIImage(data: imageData)
            }
        }

        request.resume()
    }

    //...
}

However, since the image download logic is async, it will misbehave if the cell is reused before the download completes.
i.e. Image download for the first song starts but you scroll fast enough to reuse the first cell for, lets say, the third song.
Now, when the download completes, the first image could show on the third cell.

If you face this issue then let me know and I shall update my answer.

staticVoidMan
  • 19,275
  • 6
  • 69
  • 98
  • Hey sir would you be able to help me with this? https://stackoverflow.com/questions/49639673/using-different-url-links-for-json-tableview/49644081#49644081 – Manuel Duarte Apr 04 '18 at 22:42
0

Set "WhiteLogo.png" on above your code which download image for album or set logo image if album image data is nil like guard let image = imageData else { var image : UIImage = UIImage(named:"WhiteLogo.png")!

cell.songCover.image = UIImageView(image: image) }

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {


    //1. Create A Cell
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell

    //2. Set It's Text
    cell.songTitle.text = songs[indexPath.row].title
    cell.artistLabel.text = songs[indexPath.row].artist

   //set image
    var image : UIImage = UIImage(named:"WhiteLogo.png")!
    cell.songCover.image = UIImageView(image: image)

    //3. Get The Image
    if let imageURL = URL(string: songs[indexPath.row].cover){

        let request = URLSession.shared.dataTask(with: imageURL) { (imageData, response, error) in

            if let error = error{

                print(error)

            }else{

                guard let image = imageData else { return }

                DispatchQueue.main.async {
                    cell.songCover.image = UIImage(data: image)
                    cell.setNeedsLayout()
                    cell.layoutIfNeeded()
                }

            }
        }


        request.resume()
    }

    return cell

}
Aleem
  • 3,173
  • 5
  • 33
  • 71
0
guard let image = imageData else { cell.songCover.image = UIImage(named : "your_image_name"); return }
pacification
  • 5,838
  • 4
  • 29
  • 51
Yagnesh Dobariya
  • 2,241
  • 19
  • 29
0

Please use the Kingfisher library it will download image from url and set placeholder image.Library URL:- https://github.com/onevcat/Kingfisher