ios UICollectionView在重新加载数据时滚动不平滑

iszxjhcz  于 2023-04-22  发布在  iOS
关注(0)|答案(7)|浏览(216)

在我的UICollecitonView中,我使用
self.DataTableCollectionView.reloadData()
但是随着我收集的数据越来越多,它的滚动变得粗糙,在加载一些页面后,它变得很难向上或向下滚动。它被卡住了。
最终,当我尝试一次加载1000行时,滚动工作顺利,但当我尝试使用API一次分页和加载50行时,滚动变得很难。
有什么问题吗?谁能帮我解决一下?
我不知道是什么问题?self.DataTableCollectionView.reloadData()是这个问题的原因吗?
下面是在滚动时加载数据的代码:

func scrollViewDidScroll(scrollView: UIScrollView) {

     let offsetY = scrollView.contentOffset.y
     let contentHeight = scrollView.contentSize.height

     if(offsetY > (contentHeight - scrollView.frame.size.height)){              

         let seconds = 3.0
         let delay = seconds * Double(NSEC_PER_SEC)
         let dispatchTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))

         self.loadMoreData()
         dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
             self.DataTableCollectionView.reloadData()

         })                
      }        

}

==========
我把这些细胞

self.DataTableCollectionView .registerNib(UINib(nibName: "DCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: dCellIdentifier)
self.DataTableCollectionView .registerNib(UINib(nibName: "CCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: cCellIdentifier)

并重复使用:

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

let dCell : DCollectionViewCell = collectionView .dequeueReusableCellWithReuseIdentifier(dCellIdentifier, forIndexPath: indexPath) as! DCollectionViewCell

let cCell : ContentCollectionViewCell = collectionView .dequeueReusableCellWithReuseIdentifier(cCellIdentifier, forIndexPath: indexPath) as! CCollectionViewCell       
}

=========
添加更具体的代码:
现在我更新了我的滚动功能,

func scrollViewDidScroll(scrollView: UIScrollView) {
    let offsetY = scrollView.contentOffset.y
    let contentHeight = scrollView.contentSize.height
    if(offsetY > (contentHeight - scrollView.frame.size.height)){
       var returnTableData = NSMutableArray()

       self.InspectPageId = self.InspectPageId+1
       self.dataSource.populateData(PageId:self.InspectPageId)
       returnTableData = self.dataSource.DTableDataArray

       if(returnTableData.count>0){
          for i in 0..<returnTableData.count {
             self.TableDataArray.addObject(returnTableData[i])
          }
       }
       self.NumberOfRows = self.TableDataArray.count

       dispatch_async(dispatch_get_main_queue(),{
          self.DataTableCollectionView.reloadData()
       })
   }
}

以下是手动创建集合视图的代码:

if indexPath.row == 0 {
//Here Header Cell is creating
                let dateCell : DateCollectionViewCell = collectionView .dequeueReusableCellWithReuseIdentifier(dateCellIdentifier, forIndexPath: indexPath) as! DateCollectionViewCell
                dateCell.dateLabel.font = UIFont(name:"HelveticaNeue", size: 12)
                dateCell.dateLabel.textColor = UIColor.blackColor()
                dateCell.dateLabel.textAlignment = .Left
                dateCell.dateLabel.text = UMIDDataArray[rowIndex-1] as? String
                dateCell.backgroundColor = UIColor.whiteColor()
                dateCell.layer.shouldRasterize = true
                dateCell.layer.rasterizationScale = UIScreen.mainScreen().scale
                return dateCell
            } else {
//Here Data Cell is Creating
                let contentCell : ContentCollectionViewCell = collectionView .dequeueReusableCellWithReuseIdentifier(contentCellIdentifier, forIndexPath: indexPath) as! ContentCollectionViewCell
                contentCell.contentLabel.font = UIFont(name:"HelveticaNeue", size: 12)
                contentCell.contentLabel.textColor = UIColor.blackColor()
                contentCell.contentLabel.textAlignment = .Left
                contentCell.bottomBorder.hidden  = false
                contentCell.layer.shouldRasterize = true
                contentCell.layer.rasterizationScale = UIScreen.mainScreen().scale

                let LensData:NSArray =  TableDataArray[rowIndex-1] as! NSArray
                let ColumnValue = LensData[colIndex-1] as? String
                contentCell.contentLabel.text = ColumnValue
                contentCell.backgroundColor = UIColor.whiteColor()

                return contentCell
            }

Following is the code which is use to take data from API:

//function of DataSource Class.
func populateData(PageId:Int){
var returnData = NSMutableArray()
let OtherColobjects = NSMutableArray()

let Urlpath = SetApiUrl()
let url: NSURL = NSURL(string: Urlpath)!
let urlRequest = NSURLRequest(URL: url)

let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config)

let semaphore = dispatch_semaphore_create(0)
let task = session.dataTaskWithRequest(urlRequest) {
(data, response, error) in

guard error == nil else {
return
}

guard let responseData = data else {
return
}

do {
guard let Data = try NSJSONSerialization.JSONObjectWithData(responseData, options: []) as? [String: AnyObject] else {
return
}

for anItem in Data["result"]!["DATA"] as! [Dictionary<String, AnyObject>] {
let d1 = self.checkForNull(anItem["data1"]!)
let d2 = self.checkForNull(anItem["data2"]!)
let d3 = self.checkForNull(anItem["data3"]!)
let d4 = self.checkForNull(anItem["data4"]!)
...... // Total 20 Columns

let obj = [ d1, d2, d3, d4,.............,d20 ]

OtherColobjects.addObject(obj)
}
dispatch_semaphore_signal(semaphore)
} catch {
return
}
}
task.resume()

dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
self.NumberOfRows = returnData[0].count
self.DTableDataArray = returnData[1] as! NSMutableArray
}
vsdwdz23

vsdwdz231#

在出队单元格后添加以下2行,

cell.layer.shouldRasterize = YES;
cell.layer.rasterizationScale = [UIScreen mainScreen].scale;
wj8zmpe1

wj8zmpe12#

你应该只从主线程更新你的UI,所以这样做代替...

Swift 2.x

dispatch_async(dispatch_get_main_queue()), {
                self.DataTableCollectionView.reloadData()
            }

DispatchQueue.main.async {
    self.DataTableCollectionView.reloadData()
}

如果这不能解决问题,那么你可能还需要在后台线程上调用loadMoreData()

Swift 2.x

dispatch_async(dispatch_get_global_queue(QOS_CLASS_UTILITY, 0)){
             self.loadMoreData()
        }

DispatchQueue.global(qos: DispatchQoS.QoSClass.default).async {
     self.loadMoreData()
}

由于您没有向我们展示您的loadMoreData()函数,因此不清楚您的代码是如何工作的。实际上,您可能想从loadMoreData内部调用DataTableCollectionView.reloadData(),但我无法在没有看到函数的情况下判断。请添加额外的代码

hm2xizp9

hm2xizp93#

你应该在MainThread上调度reloadData()。根据苹果文档,操作UI应该总是在MainThread中完成。

bvk5enib

bvk5enib4#

如果self.loadMoreData()不是异步的,它会阻塞你的UI。self.DataTableCollectionView.reloadData()应该在主线程上从self.loadMoreData()调用。
即使这不是阻塞,你也会在每个页面上多次调用loadMoreData()。你应该添加一个布尔值来检查你是否已经加载了数据,让我们称之为isLoading。当你初始化viewcontroller时,将isLoading设置为false。在self.loadMoreData()中将其设置为true,并在scrollViewDidScroll(scrollView: UIScrollView)中更改check,因此它看起来像这样:

if(offsetY > (contentHeight - scrollView.frame.size.height)) && !isLoading{  
    self.loadMoreData()
}
gev0vcfq

gev0vcfq5#

在主队列中重新加载搭配

dispatch_async(dispatch_get_main_queue(),{
   self.DataTableCollectionView.reloadData()
}
fjaof16o

fjaof16o6#

尝试将您的reload collectionview从scrollviewdidscroll移动到loadmoredata()
public void run(){
/* 1.列出项目2.然后在最后调用realoadata 3.如果单元格中有图像,则使用图像缓存,可以编程图像缓存或使用SDWebImage等库 */
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),{self.DataTableCollectionView.reloadData()})
}

unhi4e5o

unhi4e5o7#

重新加载数据前禁用动画

UIView.setAnimationsEnabled(false)
collectionView.reloadItems(indexPaths)
UIView.setAnimationsEnabled(true)

对我很有效。

相关问题