![](/img/trans.png)
[英]Smooth scrolling In UICollectionView inside UICollectionViewCell
[英]UICollectionView is not scrolling smooth on reload data
在我的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
}
您应该改为在MainThread
上调度reloadData()
。 根据Apple文档,应该始终在MainThread
进行UI的操作。
如果self.loadMoreData()
不是异步的,则将阻止您的UI。 self.DataTableCollectionView.reloadData()
应该叫上主线程从self.loadMoreData()
即使没有阻塞,您loadMoreData()
每个页面上多次调用loadMoreData()
。 您应该添加一个布尔值以检查是否已经在加载数据,我们称其为isLoading
。 初始化viewcontroller时,将isLoading
设置为false。 在self.loadMoreData()
中将其设置为true,然后在scrollViewDidScroll(scrollView: UIScrollView)
更改检查,如下所示:
if(offsetY > (contentHeight - scrollView.frame.size.height)) && !isLoading{
self.loadMoreData()
}
您应该只从主线程更新UI,因此请执行此操作...
Swift 2.x :
dispatch_async(dispatch_get_main_queue()), {
self.DataTableCollectionView.reloadData()
}
迅捷3 :
DispatchQueue.main.async {
self.DataTableCollectionView.reloadData()
}
如果那不能解决问题,那么您可能还需要在后台线程上调用loadMoreData()
。
Swift 2.x :
dispatch_async(dispatch_get_global_queue(QOS_CLASS_UTILITY, 0)){
self.loadMoreData()
}
迅捷3 :
DispatchQueue.global(qos: DispatchQoS.QoSClass.default).async {
self.loadMoreData()
}
由于您尚未向我们展示您的loadMoreData()
函数,因此尚不清楚您的代码的确切工作方式。 实际上,看来您可能是从loadMoreData
内调用DataTableCollectionView.reloadData()
loadMoreData
,但我无法看到该函数。 请添加其他代码
在主队列中重新加载并置
dispatch_async(dispatch_get_main_queue(),{
self.DataTableCollectionView.reloadData()
}
在出队单元格后添加以下两行,
cell.layer.shouldRasterize = YES;
cell.layer.rasterizationScale = [UIScreen mainScreen].scale;
尝试将重新加载collectionview从scrollviewdidscroll移到loadmoredata()
func loadmoredata(){
/ * 1.列出项目2.,然后在最后3.调用realoadata。如果单元中有图像,则使用图像缓存,您可以对图像缓存进行编程,也可以使用SDWebImage等库 * /
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),{self.DataTableCollectionView.reloadData()})
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.