iOS swift UITableView ReloadData 性能

Posted

技术标签:

【中文标题】iOS swift UITableView ReloadData 性能【英文标题】:iOS swift UITableView ReloadData performance 【发布时间】:2015-04-19 19:17:02 【问题描述】:

我的 ReloadData 调用在实际 ReloadData 调用和第一次调用 tableview 的 cellForRowAtIndexPath 函数之间花费了 40 多秒。有谁知道为什么会有这样的性能下降?

这是供您参考的代码: 在我的 webAPI 数据返回并完全加载到适当的本地对象后调用此代码。

func reloadPage()


    btnMenu.hidden = false
    btnMapAll.hidden = false
    if ApplicationMode != AppMode.Normal
    
        btnUseGPS.hidden = false
    
    else
    
        btnUseGPS.hidden = true
    
    StartTime = CACurrentMediaTime()

    self.NearbyLocationsTable.reloadData()

这是我的 cellForRowAtIndexPath 函数。您可以看到我在第一次调用该函数时打印了时间。

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 

    if EndTime == nil
    
        EndTime = CACurrentMediaTime() - StartTime!
        println("cellForRowAtIndexPath Time Elapsed \(EndTime?.description)")
    
    var lobj_NearbyLocationEntry: NearbyLocationsCell? = tableView.dequeueReusableCellWithIdentifier(lc_LocationCellTableIdentifier) as? NearbyLocationsCell

    if(lobj_NearbyLocationEntry == nil)
    
        lobj_NearbyLocationEntry = NearbyLocationsCell(style: UITableViewCellStyle.Default, reuseIdentifier: lc_LocationCellTableIdentifier)
    


    lobj_NearbyLocationEntry!.ConfigureCell(gobj_NearbyLocations[indexPath.row].Title, pd_Rating: gobj_NearbyLocations[indexPath.row].Rating, ps_Distance: gobj_NearbyLocations[indexPath.row].Distance, ps_Attributes: gobj_NearbyLocations[indexPath.row].AttributesTexts, pi_RowIndex: indexPath.row)

    return lobj_NearbyLocationEntry!

打印出来的信息如下: cellForRowAtIndexPath Time Elapsed Optional("40.0729780000402")

有时经过的时间低至 12 秒,但这仍然太长了。知道是什么原因造成的吗?

我确实实现了 numberOfRowsInSection 函数。这在调用 reloadData 后的几毫秒内执行。我还实现了 willDisplayCell 函数,但它只在 cellForRowAtIndexPath 之后调用(即在 40 秒过去之后)。

非常感谢您提出想法或建议。

这是另一个代码:

协议/委托定义:

protocol LocationAPICallDelegate
    
    func LocationAPIComplete()

ViewModel 代码:

var iobj_LocationAPICompleteDelegate: LocationAPICallDelegate?

func NearbyLocationsGet(ps_Langauge: String, pi_Day_Of_Week: Int, pd_Latitude: Double, pd_Longitude: Double, pl_CityID: Int, pi_Distance: Int, pb_Rating_For_Men: Bool, pi_NumberOfEntries: Int, pb_Location_In_Metric: Bool)



    var ls_CompleteURL: String = ""
    var ls_NSURL: NSURL

    ls_CompleteURL = BuildURL(ps_Langauge, pi_Day_Of_Week: pi_Day_Of_Week, pd_Latitude: pd_Latitude, pd_Longitude: pd_Longitude, pl_CityID: pl_CityID, pi_Distance: pi_Distance, pb_Rating_For_Men: pb_Rating_For_Men, pi_NumberOfEntries: pi_NumberOfEntries, pb_Location_In_Metric: pb_Location_In_Metric)


    var request : NSMutableURLRequest = NSMutableURLRequest()
    ls_NSURL = NSURL(string: ls_CompleteURL)!

    let urlSession = NSURLSession.sharedSession()

    let jsonQuery = urlSession.dataTaskWithURL(ls_NSURL, completionHandler:  data, response, error -> Void in
        if (error != nil) 
            println(error.localizedDescription)
        
        var err: NSError?

        var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as
            [[String:AnyObject]]

        if (err != nil) 
            println("JSON Error \(err!.localizedDescription)")
        
        else
        
            self.LoadJSONLocationDataToObjects(jsonResult)
            self.iobj_LocationAPICompleteDelegate?.LocationAPIComplete()
        

    )
    jsonQuery.resume()


您可以在下面的 ViewController 代码中看到委托被调用。

class NearbyLocationsViewController: UIViewController,      UITableViewDataSource, UITableViewDelegate, LocationAPICallDelegate, DOWAPICallDelegate, SideBarDelegate, GPSLocationDelegate

然后我声明一个 ViewModel 类的实例

let iobj_NearbyLocationsVM: NearbyLocationsViewModel = NearbyLocationsViewModel()

然后在 viewDidLoad 我将 ViewModel 的委托设置为 self 如下:

iobj_NearbyLocationsVM.iobj_LocationAPICompleteDelegate = self

然后当数据全部加载到 ViewModel 中时调用委托函数,使用以下调用 ReloadPage 的方法

func LocationAPIComplete()

    reloadPage()

如果有人想查看任何其他代码,请告诉我。提前感谢您的任何帮助。

【问题讨论】:

您声明您正在从 API 加载数据,您是否在数据调用的完成处理程序中编辑 UI?如果你这样做,你deck主线程吗? 我在 ViewModel 类中使用委托,并在数据全部下载并加载到对象中时调用委托的方法。该委托是调用重新加载页面功能的地方。因此,据我所知,这一切都在主线程上运行。我已经用我的 api 调用和委托代码更新了这个问题,以防我遗漏了什么。 在你调用附近LocationGet中的委托函数之前尝试去主线程队列 我不明白你在调用 nearLocationGet 中的委托函数之前先装到主线程是什么意思。你能提供一个例子来指向它的文档吗? 【参考方案1】:

所以我对 milo526 的回答进行了一些调查,发现如下更改对我的代表的调用似乎已经解决了问题。

            //Switch back to main thread
            dispatch_async(dispatch_get_main_queue())  ()
                self.iobj_LocationAPICompleteDelegate?.LocationAPIComplete()
            

我想我现在的重要评论/声明是——没有人应该发布使用 NSURLSession.sharedSession() 和 dataTaskWithURL 的示例,而不解决闭包中所需的线程切换。 :)

【讨论】:

以上是关于iOS swift UITableView ReloadData 性能的主要内容,如果未能解决你的问题,请参考以下文章

ios开发系列之Swift_UI_UITableView

iOS开发之UITableView的使用(swift)

iOS开发之UITableView的使用(swift)

iOS开发之UITableView的使用(swift)

iOS / Swift 3.0:如何确定 UITableView 中当前可见的行?

UITableView 不滚动到底部(Swift IOS)