重新加载表格视图后的抖动动作

Posted

技术标签:

【中文标题】重新加载表格视图后的抖动动作【英文标题】:Jerking motion after table view is reloaded 【发布时间】:2015-08-08 13:46:40 【问题描述】:

每当我重新加载行并向上滚动时,我都会感到奇怪的抽搐动作。向下滚动没问题,但向上滚动会导致可怕的抖动效果,导致应用无用。

我不仅附上了 cellforrowatindex 路径的代码,还附上了按钮的代码。

行的单元格:

override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!, object: PFObject!) -> PFTableViewCell! 
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! TableViewCell
    cell.nopebutton.tag = indexPath.row
    cell.nicebutton.tag = indexPath.row
    cell.killText.text = object.valueForKey("text") as! String
    cell.layoutMargins = UIEdgeInsetsZero
    cell.killText.numberOfLines = 0
    let score = object.valueForKey("count") as! Int
    cell.count.text = "\(score)"
    if cell.count.text == "\(0)"
    
        cell.count.textColor = UIColor.grayColor()
    
    if cell.count.text > "\(0)"
    
        cell.count.textColor = UIColor(red: 42.0/255, green: 204.0/255, blue: 113.0/255, alpha: 1)
    
    if cell.count.text < "\(0)"
    
        cell.count.textColor = UIColor(red: 231.0/255, green: 76.0/255, blue: 50.0/255, alpha: 1)
    
    if cell.count.text == "\(50)"
    
        cell.count.textColor = UIColor(red: 249.0/255, green: 191.0/255, blue: 59.0/255, alpha: 1)
    


    if let dict : NSDictionary = NSUserDefaults.standardUserDefaults().objectForKey("userNiceNopeDictionary") as? NSDictionary 
        cell.nicebutton.enabled = true
        cell.nopebutton.enabled = true
        if let nice  = dict[object.objectId] as? Bool
            if nice 
                cell.nicebutton.enabled = false
            
            else 
                cell.nopebutton.enabled = false
            
        
    

    let dateUpdated = object.createdAt as NSDate
    let dateFormat = NSDateFormatter()
    dateFormat.dateFormat = "h:mm a"
    cell.time.text = (NSString(format: "%@", dateFormat.stringFromDate(dateUpdated)) as String) as String
    let replycnt = object.objectForKey("replies") as! Int

    if cell.count.text == "\(-10)"
    
        object.deleteInBackground()
    


    return cell


按钮

@IBAction func topButton(sender: AnyObject) 

  var button = sender as! UIButton
//        var view = button.superview
//        
//        var otherButton = view?.viewWithTag(102) as! UIButton
//        var label = button.superview!.viewWithTag(110) as! UILabel
//        otherButton.enabled = true
//        button.enabled = false

    var rowNumber = button.tag

    var mutableDict = NSMutableDictionary()
    if let dict = NSUserDefaults.standardUserDefaults().objectForKey("userNiceNopeDictionary") 
        mutableDict = dict.mutableCopy() as! NSMutableDictionary
    

    let obj = self.objects[rowNumber] as! PFObject

    mutableDict.setValue(true, forKey: obj.objectId)
    NSUserDefaults.standardUserDefaults().setObject(mutableDict, forKey: "userNiceNopeDictionary")
    NSUserDefaults.standardUserDefaults().synchronize()
    let hitPoint = sender.convertPoint(CGPointZero, toView: self.tableView)
    let hitIndex = self.tableView.indexPathForRowAtPoint(hitPoint)
    let object = objectAtIndexPath(hitIndex)
    object.incrementKey("count")
    //label.text = object.objectForKey("count") as! String
//        self.tableView.reloadData()
    object.save()
    self.tableView.reloadRowsAtIndexPaths([hitIndex!], withRowAnimation: UITableViewRowAnimation.None)



@IBAction func bottomButton(sender: AnyObject) 

    var button = sender as! UIButton
    var rowNumber = button.tag

    var mutableDict = NSMutableDictionary()
    if let dict = NSUserDefaults.standardUserDefaults().objectForKey("userNiceNopeDictionary") 
        mutableDict = dict.mutableCopy() as! NSMutableDictionary
    

    let obj = self.objects[rowNumber] as! PFObject

    mutableDict.setValue(false, forKey: obj.objectId)
    NSUserDefaults.standardUserDefaults().setObject(mutableDict, forKey: "userNiceNopeDictionary")
    NSUserDefaults.standardUserDefaults().synchronize()

    let hitPoint = sender.convertPoint(CGPointZero, toView: self.tableView)
    let hitIndex = self.tableView.indexPathForRowAtPoint(hitPoint)
    let object = objectAtIndexPath(hitIndex)
    object.incrementKey("count", byAmount: -1)
    self.tableView.reloadRowsAtIndexPaths([hitIndex!], withRowAnimation: UITableViewRowAnimation.None)
    object.save()


override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) 
    if(segue.identifier == "killDetail")
        let indexPath = self.tableView.indexPathForSelectedRow()
        let obj = self.objects[indexPath!.row] as! PFObject
        let detailVC = segue.destinationViewController as! DetailViewController
        detailVC.kill = obj
    



我的印象是我的身高有问题,所以我也包含了该代码。

 override func viewDidLoad() 
    super.viewDidLoad()
    self.tableView.separatorInset = UIEdgeInsetsZero
    self.tableView.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0)
    self.tableView.separatorColor = UIColor(red: 236.0/255, green: 240.0/255, blue: 241.0/255, alpha: 1)
    navigationController?.tabBarController?.tabBar.hidden = true
    tabBarController?.tabBar.hidden = true
    self.tableView.estimatedRowHeight = 60
    self.tableView.rowHeight = UITableViewAutomaticDimension
    locationManager.desiredAccuracy = 1000
    locationManager.delegate = self
    locationManager.requestWhenInUseAuthorization()
    locationManager.startUpdatingLocation()

我这辈子都想不通是什么原因导致了这个混蛋。就像我说的,我认为这可能与行高的自动尺寸有关,但是当我改变这个问题时,问题仍然很明显。

【问题讨论】:

你无法从你的 gif 混蛋动作中分辨出来,但我以前见过这种情况。老实说,我很惊讶您没有看到这种行为向下滚动。应该双向发生。无论如何,就我而言,每次显示单元格时,我都会进行大量处理。您的问题仅在于覆盖 func tableView。尝试注释掉 NSDictionary 和 dateFormat 之类的代码,看看是否有帮助。 @SamB 这些是我尝试的第一件事。在我重建它之前,我遗漏了字典和日期格式,但我仍然遇到了问题。 因为我看不出你的代码有什么问题,在这一点上它是一个消除过程的问题。注释掉 let cell = tableView 中的所有内容,并开始一次添加几行代码。另外,请尝试在实际设备上进行测试。也许您的模拟器或 Xcode 正在耗尽内存或空间。抱歉,伙计,这些是最难调试的问题 @SamB 是的,我也在手机上测试过,同样的问题。老实说,这真是太可惜了,这是阻止我继续分发的唯一小问题。我将不得不真正把所有东西都分开来看看发生了什么。 估计高度是否接近实际行高?当我切换到较大的动态类型大小时,我会在向上滚动时得到这个。在下降的过程中似乎无法计算某些行大小,但是当它返回时会计算,从而导致跳跃。没有修复(还没有!),但我在其他地方看到了 cmets 1 和 2。在我的情况下,它是我的大型(高)表视图之一,它展示了这一点 - 顶部附近的单元格似乎计算得很好,但是一旦你走到这里,它就会落到一点点。甚至可能只是一个 ios 错误。 【参考方案1】:

    每次从单元格出列时,不要从用户默认值中读取该字典。在tableView(cellForRowAtIndexPath: 之外执行一次。在viewDidLoad 或其他地方做。不过,一旦它在内存中就可以从字典中挑选出一个元素……您只是不想每次单元格出列时都从磁盘(或闪存,我猜)读取。

    如果字典因任何原因在其他地方被更改并且您希望保持一致的状态,请一次性读取字典并在控制器/视图控制器之间传递它(通过,例如prepareForSegue)和更改时将其写入用户默认值。

    日期格式化器可能不是那么大或复杂的对象,但你只需要制作一次,然后可以重复使用它,所以我建议你也只创建一次。

编辑:如果您在向上滚动时遇到问题,可能是估计的行高与实际的行高不匹配。尝试移除估计的高度。

【讨论】:

NSDateFormatter 的创建成本难以置信。你不应该在 tableView:cellForRowAtIndexPath 中创建 NSDateFormatter 实例。 nshipster.com/nsformatter

以上是关于重新加载表格视图后的抖动动作的主要内容,如果未能解决你的问题,请参考以下文章

在表格视图中的所有单元格都已加载后,重新加载表格视图单元格内的集合视图

使用导致崩溃的搜索结果更新表视图

滚动或重新加载表格视图后视图位置更改

重新加载后的 NSTableView 通知

实时重新加载表格视图

重新加载单元格中没有图像的表格视图重新加载