swift:从本地json文件填充的uitableview在滚动时严重干扰

时间:2018-01-18 02:13:24

标签: ios json swift uitableview

当点击按钮以切换到tableview时,它需要大约5秒才能进行切换。在它最终分段之后,当桌面视图滚动时,它会断断续续并且有时会崩溃。 tableview从本地json文件填充并引用本地映像。图像优化为低尺寸。造成这种情况的原因是什么?我如何优化/修复我的代码以阻止这种情况发生?

import UIKit

class PDList: UIViewController, UITableViewDelegate, UITableViewDataSource {

@IBOutlet weak var pdTableView: UITableView!

var pdArt = [Decode]()

override func viewDidLoad() {
    super.viewDidLoad()

    json()

    pdTableView.delegate = self
    pdTableView.dataSource = self

}

func json() {

    let path = Bundle.main.path(forResource: "palmdesert", ofType: "json")
    let url = URL(fileURLWithPath: path!)

    do {
        let data = try Data(contentsOf: url)
        self.pdArt = try JSONDecoder().decode([Decode].self, from: data)
    }
    catch {}

}

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

}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = UITableViewCell(style: .subtitle, reuseIdentifier: "pdCell")
    let image = UIImage(named: pdArt[indexPath.row].pic)
    cell.textLabel?.text = pdArt[indexPath.row].art
    cell.detailTextLabel?.text = pdArt[indexPath.row].artist.capitalized
    cell.imageView?.image = image 

    return cell
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 100
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    performSegue(withIdentifier: "pdDetail", sender: self)
    self.pdTableView.deselectRow(at: indexPath, animated: true)
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if let destination = segue.destination as? PDDetail {
        destination.pdArt = pdArt[(pdTableView.indexPathForSelectedRow?.row)!]
    }
}

@IBAction func done(sender: AnyObject) {
    dismiss(animated: true, completion: nil)
}

}

JSON示例:

{
  "art": "Agave",
  "desc": "Agave by Michael Watling serves as the City's entry monument and is inspired by the imagery of the agave, a succulent native to the desert.  The stone forms are representative of Palm Desert's many well-managed resources for survival and growth.",
  "artist": "Michael Watling",
  "lat": 33.7215,
  "long": -116.362,
  "pic": "test.png"
  }

时间档案: Time Profile Time Profile2

如果您需要任何其他信息,请与我们联系。任何帮助表示赞赏。

3 个答案:

答案 0 :(得分:1)

我构建了一个样本UITableView项目,其中包含一个包含4032 × 3024的20个大jpeg图片的资源库,可以通过UIImage(named:)输入到我的单元格。

对于120 x 70的图片视图来说,这是一个极大的过度规范,所以最大要求为360 x 210

时间分析器显示这是为了滚动一批全新的12个单元格。

enter image description here

每个细胞大约54ms(650/12)。然而,即使是大型JPG也会利用硬件解码,因此不好。

60Hz刷新的现代iWidget每帧最多可刷新16ms以刷新单元。所以我得到了口吃。

用适当缩放的图像(360 x 210)替换图像可以得到这个。

enter image description here

每个细胞大约14ms。桌子滚动大多是平滑的。

所以这里的问题很可能是其中之一。

  • 您的图片太大了。确保您的资源的像素大小为图像视图大小的3x
  • 您的图片不是PNG或JPEG图片,无法切换到硬件解码器或使用pngcrush处理。确保您的图像是PNG或JPEG。例如GIF会很糟糕。
  • 当JPG可能更合适时,您正在使用PNG。真实世界的图像最好是JPG。线条艺术/纯色最好是PNG。

答案 1 :(得分:0)

每次都将单元格出列而不是创建新单元格。将 cellForRow 更改为以下内容:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  let cell = tableView.dequeueReusableCellWithIdentifier("pdCell", forIndexPath: indexPath)
  let image = UIImage(named: pdArt[indexPath.row].pic)
  cell.textLabel?.text = pdArt[indexPath.row].art
  cell.detailTextLabel?.text = pdArt[indexPath.row].artist.capitalized
  cell.imageView?.image = image 

  return cell
}

答案 2 :(得分:0)

我的想法是创建一个类或这样的结构。

struct ObjectFromJSON {
    var art = ""
    var desc = ""
    var artist = ""
    var lat = 0.0
    var long = 0.0
    var pic = ""
}

您解码数据的位置创建一个数组:

var decodedData = [ObjectFromJSON]()

然后将所有解码数据添加到此数组。如果这样做无济于事,那么尝试添加一个名为SwiftyJSON的CocoaPod,它可以使JSON解码变得轻而易举,并可能有所帮助。

解码后

将信息设置为ObjectFromJSON对象并将其附加到decodeData数组。

let decodedArt = json["art"].stringValue
let decodedDesc = json["desc"].stringValue
let decodedArtist = json["artist"].stringValue
let decodedLat = json["lat"].doubleValue
let decodedLong = json["long"].doubleValue
let decodedPic = json["pic"].stringValue

let newObject = ObjectFromJSON(art: decodedArt, desc: decodedDesc, artist: decodedArtist, lat: decodedLat, long: decodedLong, pic: decodedPic) 

decodedData.append(newObject)

这是基于你的JSON但是如果你在json中有多个对象而不是将它们放入一个数组然后解码看起来会有点不同,例如,如果你对对象进行编号而不是像:

let decodedArt = json[0]["art"].stringValue

如果您有多个JSON文件,那么第一个解决方案应该没问题