Swift4 UITableView:正确加载JSON数据但在赋值时抛出错误

时间:2018-06-15 18:25:56

标签: json swift4

我有一些看起来像这样的JSON数据

{
"fullName": "John Doe",
"imageUrl": "https://www.example.com/images/about/team/john.jpg",
"titles": [
  "Founder & President",
  "Advisor"
]
},
  {
"fullName": "Jane Doe",
"imageUrl": "https://www.example.com/images/about/team/jane.jpg",
"titles": [
  "Executive Vice President",
  "Director of Advisor Services and Marketing"
]
},

数据被加载并正确解析,但是当我运行代码时出现错误。我认为它与具有多个标题的标题部分有关,并且它不知道如何正确显示标题。

这是我的代码。

这是初始结构。

import UIKit

class Managers: Codable {
let managers: [Manager]

init (managers: [Manager]) {
    self.managers = managers
}
}

class Manager: Codable {
let imageUrl: String?
let fullName: String?
let titles: [titles]

init(imageUrl: String?, fullName: String?, titles: [titles]) {
    self.imageUrl = imageUrl
    self.fullName = fullName
    self.titles = titles
}

struct titles: Codable {
    let title: String
}
}

这是显示图像,名称和标题布局的管理单元格。

import UIKit

class ManagementCell: UITableViewCell {

@IBOutlet weak var imageUrl: UIImageView!
@IBOutlet weak var fullNameLbl: UILabel!
@IBOutlet weak var titlesLbl: UILabel!

override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code
}

override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    // Configure the view for the selected state
}

}

这是视图控制器

import UIKit

class ManagementViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
final let url = URL(string: "Data from above goes here")
private var managers = [Manager]()

@IBOutlet weak var tableView: UITableView!    
override func viewDidLoad() {
    super.viewDidLoad()
    downloadJson()
    tableView.tableFooterView = UIView()
}


func downloadJson() {
    guard let downloadURL = url else { return }
    URLSession.shared.dataTask(with: downloadURL) { data, urlResponse, error in
        guard let data = data, error == nil, urlResponse != nil else {
            print("Something went wrong")
            return
        }
        print("downloaded")
        do
        {
            let decoder = JSONDecoder()
            let downloadedManagers = try decoder.decode([Manager].self, from: data)
            self.managers = downloadedManagers
            DispatchQueue.main.async {
                self.tableView.reloadData()
            }
        } catch {
            print("Something went wrong after download")
        }
        }.resume()
}

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

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    guard let cell = tableView.dequeueReusableCell(withIdentifier: "ManagementCell") as? ManagementCell else { return UITableViewCell() }


    cell.fullNameLbl?.text = managers[indexPath.row].fullName
    cell.titlesLbl?.text = managers[indexPath.row].titles

    if let imageURL = URL(string: managers[indexPath.row].imageUrl!) {
        DispatchQueue.global().async {
            let data = try? Data(contentsOf: imageURL)
            if let data = data {
                let image = UIImage(data: data)
                DispatchQueue.main.async {
                    cell.imageUrl.image = image
                    cell.imageUrl.layer.cornerRadius = 60
                    cell.imageUrl.clipsToBounds = true
                    cell.imageUrl.contentMode = .scaleAspectFit
                    cell.imageUrl.backgroundColor = UIColor.lightGray
                    cell.imageUrl.layer.borderWidth = 5
                    cell.imageUrl.layer.borderColor = UIColor.clear.cgColor
                }
            }
        }
    }
    return cell
}

这行代码抛出错误:     cell.titlesLbl?.text = managers [indexPath.row] .titles

错误是无法指定类型'[Manager.titles]'的值来键入'String?'

有没有人有解决方法。我相信我必须为标题创建一个单独的循环,因为它还有一系列选项。任何建议都将非常感谢。

如果图像丢失,则单独注释图像会导致应用程序崩溃。如果JSON数据中的图像不存在,如何设置通用图像?

1 个答案:

答案 0 :(得分:0)

因为managers[indexPath.row].titles返回String s的数组。窥视您的数据,看起来该数组中的第一个标题是经理持有的最新标题。您可以附加索引或致电.first以获取该标题:

cell.titlesLbl?.text = managers[indexPath.row].titles.first?.title

// or
cell.titlesLbl?.text = managers[indexPath.row].titles[0].title

// or to show all past titles, comma separated                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
cell.titlesLbl?.text = managers[indexPath.row].titles
                         .map({ $0.title })
                         .joined(separator: ", ")

不同之处在于,如果.first数组为空,titles不会抛出错误。你得到一个空白标签。如果您的数组为空,[0]将抛出索引超出范围错误。