gpt4 book ai didi

ios - UICollectionViewCell 消息在出队后立即发送到已释放的实例

转载 作者:行者123 更新时间:2023-11-30 13:44:57 25 4
gpt4 key购买 nike

我有一个 UICollectionViewCell 正在出列以供重用。我最近引入了一个滑动抽屉功能,它基本上是一个隐藏 View ,当用户滑动时会显示出来。

在最后一次更改之后,这似乎会造成实例在初始化时被释放的情况。报告僵尸的确切位置是对“addGestureRecognizers()”的调用,该调用是从 setupSlidingDrawer() 调用的,而 setupSlidingDrawer() 又是从 init 函数调用的。

我附上了僵尸调用前后断点的图像。我整天揪着头发看着这个,却一直一片空白。

作为解决方法(黑客),我将deleteView设置为实例变量,这似乎可以防止类释放,因为保留计数不会减少。

我觉得我的 Collection View 单元/ Controller 的代码非常标准,我没有做任何疯狂的事情。

这似乎是苹果的一个错误,但我似乎无法在互联网上找到任何东西来证明这一点。如果

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()
}

enter image description here

最佳答案

请注意,确保返回 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()
}

编辑

正如我看到的屏幕截图,日志是有关优化的警告。整个赋值可能不起作用,因为稍后不会使用该变量。

关于ios - UICollectionViewCell 消息在出队后立即发送到已释放的实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35076277/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com