UIImage从json请求返回nil到mysql数据库以获得tableView单元格图像?

Posted

技术标签:

【中文标题】UIImage从json请求返回nil到mysql数据库以获得tableView单元格图像?【英文标题】:UIImage returning nil from json request to mysql database for tableView cell image? 【发布时间】:2017-07-31 00:08:22 【问题描述】:

我无法将图像返回到 tableView 单元格。

当我将所有的 recipientImg 参数更改为字符串时,一切运行正常,但是当我将 recipientImg 参数更改为 UIImage 时,我得到了(下载的数据 致命错误:在展开可选值时意外发现 nil) (lldb)

Ps 我正在尝试将数据库中的文件路径作为图像返回。其他两个字符串在 tableView 中作为字符串返回,但我无法让 imageView 返回图像。

有什么建议吗?

This is the JSON file on the server from the database 我也在数据库中使用 RecipientImg 作为 [varchar]

这里是 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



这里是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)

    )
 


这里是viewedMeController.swift 导入 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

【问题讨论】:

还有一句话,你的命名约定真的很糟糕,你应该总是对类和协议使用大写的名字,而对变量名使用驼峰式命名。 【参考方案1】:

问题在于您的viewedMeModel2.swift,在这一行:

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

条件解包结果总是返回recipientImg = nil,因为jsonElement["RecipientImg"]是一个字符串,它不能被强制转换为UIImage。 您应该将代码重写为:

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)
    

【讨论】:

这非常正确,但我很确定 UIImage(named: String) 初始化程序仅用于您存储在应用程序主包中的图像。 (您本地存储在图像资产文件夹中的图像) 你说得对,我只是假设 PO 将图像存储在他的图像资产中,因为他的示例 json 的内容。是的,我的 UIImage(name:) 可能是错误的 :) 完全不用担心!您可能是正确的,他将它们存储在本地。只是想指出这一点,以防他不是,仅此而已! :) 实际上我并没有在本地存储图像。我正在使用 mysql 数据库,并将图像文件存储在我的文件系统上。我只是将图像的路径存储在数据库中【参考方案2】:

我的猜测是 jsonElement["RecipientImg"] 返回 String 而不是 UIImage,所以你得到 nil 因为你不能将字符串转换为图像。尝试从jsonElement["RecipientImg"] 获取图像网址,然后从该网址创建UIImage。像这样的:

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

如果您要获取某种数据对象,也可以使用 UIImage 初始化程序 init?(data: Data)

同样,jsonElement["RecipientImg"] 的对象可能无法转换为UIImage,我猜它是String。找出它是什么以及你可以将它转换成什么,然后使用文档中适当的 UIImage 初始化程序。

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

【讨论】:

以上是关于UIImage从json请求返回nil到mysql数据库以获得tableView单元格图像?的主要内容,如果未能解决你的问题,请参考以下文章

UIImage imageNamed 返回 nil

iPhone - UIImage imageWithData 返回 nil

UIImage返回nil但存在

无法设置 UIImage,总是返回 nil

使用 PHImageManager 时,PHAsset 返回 UIImage 的 nil 值

UIImage 仅在 UIImageView 中返回 nil