我有一个UICollectionViewCell,它正在出列以供重用。我最近推出了一个滑动抽屉功能,它基本上是一个隐藏视图,当用户滑动时会显示该视图。
在最后一次更改之后,这似乎创建了一个实例在初始化时被释放的情况。报告Zombie的确切位置是在" addGestureRecognizers()"从setupSlidingDrawer()调用,然后从init函数调用它。
我在Zombie电话之前和之后附上了断点的图像。我一整天都在拉着头发看着这个并继续画一个空白。
作为一种解决方法(hack)我已经使deleteView成为一个实例变量,这似乎使得类不会被释放,因为保留计数不会减少。
我觉得我的收藏视图单元/控制器的代码非常标准,我没有做任何疯狂的事情。
这似乎是一个苹果虫,但我似乎无法在网络上找到任何东西来证明它。如果
class MomentsViewCell : UICollectionViewCell, UIGestureRecognizerDelegate {
static let reuseIdentifier = "MomentsViewCell"
let imageView = UIImageView()
let activityIndicator = UIActivityIndicatorView()
let shareButton = UIButton()
var shareCallback: (() -> ())?
var isSwiped = false
let overlayViewTag = 999
var delegate: MomentsViewController?
let shareButtonLength: CGFloat = 44
lazy var drawerWidth: CGFloat = {
self.frame.width * 0.15
}()
override init(frame: CGRect) {
super.init(frame: frame)
contentView.addSubview(imageView)
imageView.contentMode = UIViewContentMode.ScaleAspectFit
imageView.snp_makeConstraints { (make) -> Void in
make.centerX.equalTo(self.contentView.snp_centerX)
make.width.equalTo(self.contentView.snp_width)
make.top.equalTo(self.snp_top)
make.bottom.equalTo(self.snp_bottom)
}
contentView.addSubview(activityIndicator)
activityIndicator.hidesWhenStopped = true
activityIndicator.snp_makeConstraints { (make) -> Void in
make.center.equalTo(self.snp_center)
}
let shareImage = UIImage(named: "share-moment")
shareButton.setImage(shareImage, forState: .Normal)
shareButton.addTarget(self, action: "didTapShareButton", forControlEvents: .TouchUpInside)
shareButton.enabled = false
shareButton.alpha = 0.0
imageView.addSubview(shareButton)
imageView.userInteractionEnabled = true
shareButton.snp_makeConstraints { (make) -> Void in
let size = CGSizeMake(shareButtonLength, shareButtonLength)
var offset = shareButtonLength / 2
if let imageLength = shareImage?.size.height {
offset = (shareButtonLength - imageLength) / 2
}
make.bottom.equalTo(self.imageView).multipliedBy(0.95).offset(offset)
make.right.equalTo(self.imageView).multipliedBy(0.95).offset(offset)
make.size.equalTo(size)
}
setupSlidingDrawer()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func prepareForReuse() {
super.prepareForReuse()
imageView.image = nil
exitDeleteMode()
}
func enableSharing() {
shareButton.enabled = true
shareButton.alpha = 1.0
}
func didTapShareButton() {
shareCallback?()
}
func setupSlidingDrawer() {
let deleteView = UIView(frame: CGRectMake(self.frame.width - drawerWidth, self.frame.origin.y, drawerWidth, self.frame.height))
deleteView.backgroundColor = UIColor.whiteColor()
let deleteGradientLayer = CAGradientLayer()
deleteGradientLayer.frame = deleteView.bounds
deleteGradientLayer.colors = [UIColor(hex: 0xE8557C).CGColor, UIColor(hex: 0xCC2B49).CGColor]
deleteView.layer.insertSublayer(deleteGradientLayer, atIndex: 0)
let trashButton = UIButton()
trashButton.setImage(UIImage(named: "trash_can"), forState: UIControlState.Normal)
trashButton.addTarget(self, action: Selector("didPressDelete"), forControlEvents: .TouchUpInside)
deleteView.addSubview(trashButton)
deleteView.bringSubviewToFront(trashButton)
trashButton.snp_makeConstraints(closure: { (make) -> Void in
make.center.equalTo(deleteView.snp_center)
make.width.equalTo(deleteView.snp_width).multipliedBy(0.354)
make.height.equalTo(deleteView.snp_height).multipliedBy(0.07)
})
contentView.addSubview(deleteView)
deleteView.snp_makeConstraints(closure: { (make) -> Void in
make.left.equalTo(self.imageView.snp_right)
make.height.equalTo(self.contentView.snp_height)
make.width.equalTo(drawerWidth)
})
addGestureRecognizers()
}
func addGestureRecognizers() {
let swipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: Selector("didSwipeCell:"))
swipeGestureRecognizer.delegate = self
swipeGestureRecognizer.direction = .Left
self.addGestureRecognizer(swipeGestureRecognizer)
}
class MomentsViewController: ContainerSubController, UICollectionViewDelegate, UICollectionViewDataSource {
var moments: [Moment] = []
let layout = UICollectionViewFlowLayout()
var collectionView = UICollectionView(frame: CGRectZero, collectionViewLayout: UICollectionViewFlowLayout())
let headerIdentifier = "headerCellIdentifier"
let headerLabelText = "Moments"
let headerCellHeight: CGFloat = 103.0
let noMomentsLabelText = "It's looking pretty empty in here! Assign a Moments action (Share Moment To Twitter) to a Hot Key to get started."
let noMomentsReuseIdentifier = "NoMoments"
var currentSwipedCellIndexPath: NSIndexPath?
override func viewDidLoad() {
super.viewDidLoad()
layout.minimumLineSpacing = 0
collectionView = UICollectionView(frame: view.frame, collectionViewLayout: layout)
collectionView.showsVerticalScrollIndicator = false
collectionView.backgroundColor = UIColor.clearColor()
collectionView.registerClass(MomentsViewCell.self, forCellWithReuseIdentifier: MomentsViewCell.reuseIdentifier)
collectionView.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: noMomentsReuseIdentifier)
collectionView.registerClass(UICollectionViewCell.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: headerIdentifier)
collectionView.delegate = self
collectionView.dataSource = self
view.backgroundColor = UIColor.blackColor()
view.addSubview(collectionView)
collectionView.snp_makeConstraints { (make) -> Void in
make.height.equalTo(view)
make.width.equalTo(view)
make.center.equalTo(view)
}
setupTransitionToMainButton()
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
refreshMoments()
collectionView.reloadData()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "handleMomentSavedNotifcation", name: MomentNotifcation.MomentSaved.rawValue, object: nil)
}
//MARK: UICollectionViewDataSource
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
guard let momentsViewCell = collectionView.dequeueReusableCellWithReuseIdentifier(MomentsViewCell.reuseIdentifier, forIndexPath: indexPath) as? MomentsViewCell, moment = moments[safe:indexPath.row] else {
return MomentsViewCell()
}
答案 0 :(得分:0)
在警卫中,请务必返回momentsViewCell
,即之前出列的人。
例如:
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
if let momentsViewCell = collectionView.dequeueReusableCellWithReuseIdentifier(MomentsViewCell.reuseIdentifier, forIndexPath: indexPath) as? MomentsViewCell {
return momentsViewCell
else {
return MomentsViewCell()
}
修改强>
在我看到屏幕截图时,日志会警告优化。整个赋值可能不起作用,因为稍后不会使用该变量。