2

This is a cardCollectionView app, I am trying to delete item with longpress and show a delete button in item. I can delete item already, but my item doesn't reload to an empty place. I found that the problem is because there is a protocol function never working.

Here's my protocol:

@objc protocol ActionDelegation:class {

func deleteCell(_ indexPath:IndexPath, _ cellView:MyCollectionViewCell)
func hideAllDeleteBtn()
func showAllDeleteBtn()    
}

The hideAllDeleteBtn() and showAllDeleteBtn() function are working well, but deleteCell(_ indexPath:IndexPath, _ cellView:MyCollectionViewCell) function never works.

weak var delegation : ActionDelegation!

I try to print() here, but never run in this function at all (in MyCollectionViewCell class)

func animationDidStop(_ theAnimation: CAAnimation!, finished flag: Bool){
    delegation.deleteCell(path, self)
}

here is ViewController class

I did cell.delegation = self in one of my function

It should work after I tap delete button with a disspare animation,

func deleteCell(_ indexPath:IndexPath, _ cellView:MyCollectionViewCell){            print("1")
    myCollectionView.performBatchUpdates({ () -> Void in
        print("2")
        self.cellArray.removeObject(at: indexPath.row)
        self.myCollectionView.deleteItems(at: [indexPath])
        print("3")
    }, completion: {(flag:Bool) in
        print("4")
        self.myCollectionView.reloadData()
        print("5")   
    })
}

yup...this function is never working, if this is function working then empty place should not be empty. FYI the other two protocol functions are working, why only this one can't ?

Edit

This is the animation part, it is in a Animation class which extends NSObject

 class Animation: NSObject {  

   func fadeAnimation(view:UIView){
    let animation = CATransition() 
    animation.delegate = view as? CAAnimationDelegate 
    animation.duration = 0.5 
    view.layer.add(animation, forKey: nil) 
    view.isHidden = true 
}}

it will call in MyCollectionViewCell like below (in MyCollectionViewCell)

let animation = Animation()

func setAnimation(){

    animation.fadeAnimation(view: self)
}

when I delete the item, it can delete and with fade animation

when I delete it

mfaani
  • 33,269
  • 19
  • 164
  • 293
Zoe
  • 121
  • 1
  • 2
  • 8
  • If `delegation.deleteCell(path, self)` was called in your view controller, what is `path` and why did you pass `self` as the second argument. Should it be your selected `MyCollectionViewCell` instead? – Lawliet Jul 09 '17 at 13:25
  • @Lawliet hi ! the `path` is a `var path:IndexPath!` , and `self` is because `delegation.deleteCell(path, self)` is use in MyCollectionViewCell class, so I think self is ok to use ..... – Zoe Jul 09 '17 at 13:34
  • 1
    actually he doesn't need the path in (path, self). He should only be using (self), as that way he can always get the correct indexPath no matter deletion or insertion takes place by using indexPathFor(cell: cell) – Dark Innocence Jul 09 '17 at 14:21
  • @Rob hi, yes! I'm saying that method isn't called at all. there is my animation function `func fadeAnimation(view:UIView){ let animation = CATransition() animation.delegate = view as? CAAnimationDelegate animation.duration = 0.5 view.layer.add(animation, forKey: nil) view.isHidden = true }` im not sure that is what you want to see, – Zoe Jul 09 '17 at 14:50
  • @DarkInnocence hi. I don't know if I don't set `path` how can I do with `removeObject(at: indexPath.row)` ? – Zoe Jul 09 '17 at 14:52
  • 1
    @Rob thanks for telling! the `self` is `UICollectionViewCell` – Zoe Jul 09 '17 at 15:17
  • The issue is that the signature of your `animationDidStop` is incorrect. You specified an optional `CAAnimation!`. But it is not optional. – Rob Jul 09 '17 at 16:26
  • You said you have problems with closures? They are a tough subject. But once you master the basics it becomes super easy. Read this awesome [tutorial](https://www.weheartswift.com/closures/). After finishing that tutorial read [here](https://www.objc.io/books/functional-swift/preview/); read the section where it says 'First-Class Functions'. Though reading the entire page is worth the time. – mfaani Jul 09 '17 at 17:10
  • @Honey hi! thanks a lot ! I will read it ! you are so sweet~ – Zoe Jul 10 '17 at 01:04

1 Answers1

2

The animationDidStop(_:finished:) is not getting called because you've specified that the first parameter is an optional, but it's not.

By the way, if you specified that MyCollectionViewCell conformed to CAAnimationDelegate (for example, in an extension, like below), the compiler would have warned you about this issue:

error message

It should be:

extension MyCollectionViewCell: CAAnimationDelegate {
    func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
        ...
    }
}

In the future, I might suggest using block-based animation to simplify any delegate-related issues with the animation.

protocol ActionDelegate: class {
    func deleteCell(_ cell: UICollectionViewCell)
    func hideAllDeleteBtn()
    func showAllDeleteBtn()
}

class MyCollectionViewCell: UICollectionViewCell {
    weak var delegate: ActionDelegate?

    func fadeAndDelete() {
        UIView.animate(withDuration: 0.5, animations: {
            self.alpha = 0
        }, completion: { _ in
            self.delegate?.deleteCell(self)
        })
    }
}

Note, I simplified deleteCell(_:) delegate method, because you shouldn't save the IndexPath, but instead calculated it just in time:

extension ViewController: ActionDelegate {
    func deleteCell(_ cell: UICollectionViewCell) {
        guard let indexPath = myCollectionView.indexPath(for: cell) else { return }

        cellArray.removeObject(at: indexPath.row)   // I might suggest making `cellArray` a Swift array rather than a `NSMutableArray`
        myCollectionView.deleteItems(at: [indexPath])
    }

    func hideAllDeleteBtn() { ... }

    func showAllDeleteBtn() { ... }
}
Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • Thanks you much !!!! actually I am really bad with block.... But it's my problem, I will learn how to using block in future ! The answer is save my time so much, It working excellent ! but Xcode showed me this `Snapshotting a view that has not been rendered results in an empty snapshot. Ensure your view has been rendered at least once before snapshotting or snapshot after screen updates.` . I'm finding solve way! thanks you again! – Zoe Jul 09 '17 at 16:42
  • @Zoe did you see [here](https://stackoverflow.com/questions/25884801/ios-8-snapshotting-a-view-that-has-not-been-rendered-results-in-an-empty-snapsho)? – mfaani Jul 09 '17 at 17:15
  • @Honey hi! , thanks for the link, it looks use camera or UIImagePickerController?! but I don't use any of them.need to find other solution , anyway thanks! – Zoe Jul 10 '17 at 01:04