0
votes

I am having trouble returning an image to the tableView cell.

When i change all the recipientImg parameters to string everything runs fine, but when I change the recipientImg parameters to UIImage I get (Data downloaded fatal error: unexpectedly found nil while unwrapping an Optional value) (lldb)

Ps i am trying to return the file path in the database as an image. The other two strings return in the tableView as strings but i cannot get the imageView to return the image.

Any Tips?

This is the JSON file on the server from the database Also I'm using RecipientImg as [varchar] in the database

here is the viewermodel1.swift

 import UIKit

class viewedMeModel1: NSObject {
//properties

var username: String?
var messageDetail: String?
var recipientImg: UIImage?
//empty constructor

override init()
{

}

//construct with parameters

init(username: String, messageDetail: String, recipientImg: UIImage)       {

    self.username = username
    self.messageDetail = messageDetail
    self.recipientImg = recipientImg
}


//prints object's current state


}

here is the viewedMeModel2.swift

import UIKit

protocol viewedMeModel2Protocol: class {
func itemsDownloaded(items: NSArray)
}


class viewedMeModel2: NSObject {
weak var delegate: viewedMeModel2Protocol!

var data = Data()

let urlPath: String = "http://" //this will be changed to the path where .php lives

func downloadItems() {

    let url: URL = URL(string: urlPath)!
    let defaultSession = Foundation.URLSession(configuration: URLSessionConfiguration.default)

    let task = defaultSession.dataTask(with: url) { (data, response, error) in

        if error != nil {
            print("Failed to download data")
        }else {
            print("Data downloaded")
            self.parseJSON(data!)
        }

    }

    task.resume()
}

func parseJSON(_ data:Data) {

    var jsonResult = NSArray()

    do{
        jsonResult = try JSONSerialization.jsonObject(with: data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSArray

    } catch let error as NSError {
        print(error)

    }

    var jsonElement = NSDictionary()
    let locations = NSMutableArray()

    for i in 0 ..< jsonResult.count
    {

        jsonElement = jsonResult[i] as! NSDictionary

        let location = viewedMeModel1()

        //the following insures none of the JsonElement values are nil through optional binding
        if let username = jsonElement["Username"] as? String,
            let messageDetail = jsonElement["MessageDetail"] as? String,
            let recipientImg = jsonElement["RecipientImg"] as? UIImage

        {

            location.username  = username
            location.messageDetail = messageDetail
            location.recipientImg = recipientImg

        }

        locations.add(location)

    }

    DispatchQueue.main.async(execute: { () -> Void in

        self.delegate.itemsDownloaded(items: locations)

    })
 }

}

here is the viewedMeController.swift import UIKit

class ViewerViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, viewedMeModel2Protocol {


var feedItems: NSArray = NSArray()
var selectedLocation : viewedMeModel1 = viewedMeModel1()





@IBOutlet weak var viewedMe: UITableView!

override func viewDidLoad() {
    super.viewDidLoad()
self.viewedMe.delegate = self
    self.viewedMe.dataSource = self

    let ViewedMeModel2 = viewedMeModel2()
    ViewedMeModel2.delegate = self
    ViewedMeModel2.downloadItems()
    // Do any additional setup after loading the view.
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

func itemsDownloaded(items: NSArray) {

    feedItems = items
    self.viewedMe.reloadData()

}

func numberOfSections(in tableView: UITableView) -> Int {
    return feedItems.count
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    // Return the number of feed items
    return feedItems.count

}



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

    // Retrieve cell
    let cellIdentifier: String = "basicCell"
    let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier)!
    // Get the location to be shown
    let item: viewedMeModel1 = feedItems[indexPath.row] as! viewedMeModel1

    // Get references to labels of cell
    cell.UIImage?.image = item.recipientImg!
    return cell
}
2
And one remark mate, your naming convention is really bad, you should always use capitalized names for classes and protocols, and camel-cased for variable names.hoang Cap

2 Answers

1
votes

The problem is with your viewedMeModel2.swift, at this line:

let recipientImg = jsonElement["RecipientImg"] as? UIImage

the conditional unwrapped result will alway return recipientImg = nil, because jsonElement["RecipientImg"] is a string, it cannot be casted to UIImage. You should rewrite your code to this:

if let username = jsonElement["Username"] as? String,
        let messageDetail = jsonElement["MessageDetail"] as? String,
        let recipientImgString = jsonElement["RecipientImg"] as? String

    {

        location.username  = username
        location.messageDetail = messageDetail
        location.recipientImg = UIImage(named: recipientImgString)
    }
1
votes

My guess is that jsonElement["RecipientImg"] is returning a String not a UIImage, so you're getting nil because you can't cast the string as an image. Trying getting an image url from jsonElement["RecipientImg"] and then create a UIImage from that url. Something like this:

let imageURL = jsonElement["RecipientImg"] as? String
let myImage = UIImage(contentsOfFile: imageURL)

You can also use the UIImage initializer init?(data: Data) if you're getting some sort of data object.

Again, the object at jsonElement["RecipientImg"] probably can't be cast to UIImage, and my guess is that it's a String. Find out what it is and what you can cast it as, and then use the appropriate UIImage initializer from the documentation.

https://developer.apple.com/documentation/uikit/uiimage