问题描述
大家好,
我正在寻找一些有关根据indexPath行在自定义单元格中重新加载数据的提示。
上下文:
-
我有一个教学幻灯片,我正在使用
UICollectionView
。在此视图中,我为每个UICollectionViewCell
个不同的自定义对象插入自定义indexPath.row
(因此我为UICollectionView
注册了多个笔尖)。 -
在基于indexPath.row的委托方法
cellForItemAt indexPath
中,我将所需的特定自定义单元出队 -
本教程的幻灯片显示具有一些按钮,您可以使用这些按钮在特定的单元格之间导航(btw单元格占据了用户屏幕的大部分),因此您可以像“下一步”或“上一步”一样进行导航。
-
在其自己的自定义类中的每个单元格都经过一些转换定义。因此,例如1号单元格从一些自定义元素开始,然后在大约2秒钟后过渡到另一组元素。因此,我正在创建类似动画的内容。这些转换是通过
dispatchQueue.main.asyncAfter
执行的,所以我让用户阅读了我想要的第一个屏幕,然后阅读了第二个屏幕。然后,用户单击下一步按钮,然后转到另一个indexPath.row
,有时在下一个“屏幕”中还会有另一个过渡 -
因此,我的意图是当用户例如通过单击“下一步” /“后退”在单元格(
indexPath.row
/ s)之间导航时拥有“清晰的”默认视图,因此当他从Screen2转到Screen1时,我希望他从头开始查看Screen1,然后再次查看过渡。现在,它结束于我转到的最后一个屏幕。
我的实际问题:
那么,有什么方法可以用当前设计刷新单元格,还是应该更改构造集合视图的方式?
请在下面查看一些示例代码片段。
1。 VC与我的UICollectionView
class IncomingInstructionsVC: UIViewController {
@IBOutlet weak var btnBack: UIButton!
@IBOutlet weak var btnNext: UIButton!
@IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
collectionView.register(Screen1.nib,forCellWithReuseIdentifier: "Screen1ID")
collectionView.register(Screen2.nib,forCellWithReuseIdentifier: "Screen2ID")
collectionView.register(Screen3.nib,forCellWithReuseIdentifier: "Screen3ID")
collectionView.register(Screen4.nib,forCellWithReuseIdentifier: "Screen4ID")
collectionView.register(Screen5.nib,forCellWithReuseIdentifier: "Screen5ID")
collectionView.register(Screen6.nib,forCellWithReuseIdentifier: "Screen6ID")
collectionView.dataSource = self
collectionView.delegate = self
collectionView.isPagingEnabled = false
}
2。在UICollectionViewCell / s之间导航的IBActions
@IBAction func btnNextTapped(_ sender: UIButton) {
let visibleItems: NSArray = self.collectionView.indexPathsForVisibleItems as NSArray
var minItem: NSIndexPath = visibleItems.object(at: 0) as! NSIndexPath
for itr in visibleItems {
if minItem.row > (itr as AnyObject).row {
minItem = itr as! NSIndexPath
}
}
let nextItem = IndexPath(row: minItem.row + 1,section: 0)
self.collectionView.scrollToItem(at: nextItem as IndexPath,at: .left,animated: false)
}
@IBAction func btnBackTapped(_ sender: UIButton) {
let visibleItems: NSArray = self.collectionView.indexPathsForVisibleItems as NSArray
var minItem: NSIndexPath = visibleItems.object(at: 0) as! NSIndexPath
for itr in visibleItems {
if minItem.row > (itr as AnyObject).row {
minItem = itr as! NSIndexPath
}
}
let nextItem = IndexPath(row: minItem.row - 1,animated: false)
}
3。委托方法 cellForItemAt indexPath:
func collectionView(_ collectionView: UICollectionView,cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
var cell = UICollectionViewCell()
self.pageControl.currentPage = indexPath.row
switch indexPath.row {
case 0:
cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Screen1ID",for: indexPath) as! Screen1
case 1:
cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Screen2ID",for: indexPath) as! Screen2
case 2:
cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Screen3ID",for: indexPath) as! Screen3
.
.
.
continues to the end of my tutorial
.
.
.
}
return cell
}
4。使用 dispatchQueue.main.asyncAfter
逻辑
.
.
.
Some IBOutlets here....
.
.
.
override func awakeFromNib() {
super.awakeFromNib()
commonInit()
}
func commonInit() {
greyBackground.layer.cornerRadius = 10
transition1.layer.cornerRadius = 10
transition2.layer.cornerRadius = 10
self.nameIncomingLabel.text = NSLocalizedString("name_inc_head",comment: "")
self.mobileLabel.text = NSLocalizedString("mobile",comment: "")
self.declineImageView.image = UIImage(named: "Reject")
self.declineLabel.text = NSLocalizedString("Decline",comment: "")
self.acceptimageView.image = UIImage(named: "Accept")
self.acceptLabel.text = NSLocalizedString("accept",comment: "")
dispatchQueue.main.asyncAfter(deadline: .Now() + 0.5) { [self] in
//transition to "Accept Call" command
UIView.transition(with: transition1,duration: 1,options: .transitionCrossdissolve,animations: {
transition1.backgroundColor = UIColor(red: 0,green: 0,blue: 0,alpha: 0.9)
transition1Acceptimage.image = UIImage(named: "Accept")
transition1Label.font = UIFont.systemFont(ofSize: 21,weight: .semibold)
transition1Label.text = NSLocalizedString("answer_incoming_call",comment: "")
//transition to calling screen with icons
dispatchQueue.main.asyncAfter(deadline: .Now() + 1.5) { [self] in
UIView.transition(with: transition2,duration: 0.5,animations: {
transition2.backgroundColor = #colorLiteral(red: 0.3019607843,green: 0.3019607843,blue: 0.3019607843,alpha: 1)
nameIncomingLabelTransition2.text = NSLocalizedString("name_inc_head",comment: "")
....it is continuing with the closing curly braces down below...
解决方法
使可重用单元格出格的目的是避免单元格的多次创建,这些创建可以被容器视图(如表视图或集合视图)更快地重用。容器视图会缓存许多不在屏幕上的单元格,因此一旦该单元格再次可见,便可以取回该单元格。
由于您的动画是在commonInit
中实现的(仅由awakeFromNib
调用),您只能看到一次动画,因为视图仅一次加载到内存中。
您需要在单元格出队后手动调用commonInit
,而不可以通过awakeFromNib
进行调用。
或更妙的是:将仅一次内容与动画/内容初始化部分分开,然后从awakeFromNib
中调用第一个,而一旦视图退出队列,则调用后者。
这甚至更好,因为awakeFromNib
甚至在视图可见之前就被调用了,因此您甚至都不知道它何时显示。