0

Ok, I have looked at similar posts like Select items programmatically in UICollectionView and tried my own methods, but I cannot select an item in my programmatically created UICollectionView with Swift.

I am building an iMessage extension and I made the UICollectionview to store custom MSStickerViews instead of the MSStickerBrowser. I create my MSStickerViews like this, which have a custom class on the MSStickerView to detect when they are peeled or tapped:

var url: URL?
        var i = 1
        while i < 5 { //while true
            url = Bundle.main.url(forResource: "test5", withExtension: "png") //would be "test\(i)"
            print("URL IS THIS: \(url)")
            guard let url = url else { break }

            //make it a sticker
            let sticker = try! MSSticker(contentsOfFileURL: url, localizedDescription: "test\(i)")

            //let stickerView = InstrumentedStickerView(frame: CGRect(x: 0, y: 0, width: view.bounds.width*0.4, height: view.bounds.width*0.4))
            let stickerView = InstrumentedStickerView(frame: CGRect(origin: CGPoint(x: 0,y :0), size: stickerSize))
            stickerView.sticker = sticker
            stickerView.delegate = self

            starterPack.append(stickerView)

            i += 1

Then in my custom class which I adopted from another post:

protocol InstrumentedStickerViewDelegate: class {
    func stickerViewDidSelect(stickerView: MSStickerView)
    func stickerViewDidPeel(stickerView: MSStickerView)
}

class InstrumentedStickerView: MSStickerView {
    weak var delegate: InstrumentedStickerViewDelegate?

    override init(frame: CGRect) {
        super.init(frame: frame)

        for gestureRecognizer in gestureRecognizers ?? [] {
            if let tapGestureRecognizer = gestureRecognizer as? UITapGestureRecognizer {
                tapGestureRecognizer.addTarget(self, action: #selector(didTap))
            } else if let longPressGestureRecognizer = gestureRecognizer as? UILongPressGestureRecognizer {
                longPressGestureRecognizer.addTarget(self, action: #selector(didLongPress))
            }
        }


    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func didTap(tapGestureRecognizer: UITapGestureRecognizer) {
        if tapGestureRecognizer.state == .recognized {
            delegate?.stickerViewDidSelect(stickerView: self)
        }
    }

    func didLongPress(longPressGestureRecognizer: UILongPressGestureRecognizer) {
        if longPressGestureRecognizer.state == .began {
            delegate?.stickerViewDidPeel(stickerView: self)
        }
    }
}

My issue is I need to be able to PROGRAMMATICALLY (like with a button) select one of my sticker views at its place in my collection view. Meaning simulating the user tapping the sticker and making it appear in the iMessage text entry field.

I did not know how to go about just putting the sticker in the entry field directly, this is why I am going with the simulate tapping approach.

My collection view has a header, and I have tried using the following to select the item in the collection view, but despite trying to navigate the different rows/sections when I put in 0,0 nothing happens (suspect it was selecting the header) and anything else either does nothing or does Uncaught exception error:

collectionView.selectItem(at: IndexPath(row: 0, section: 1), animated: false, scrollPosition: UICollectionViewScrollPosition.left)

I have called the didTap and custom funcs from the class directly, but this did not select the sticker just called the function:

stickerViewDidSelect(stickers[1])

I need to find a way to trigger a tap event on the MSStickerView/MSSticker to put it in the entry field. How can I do this?

Community
  • 1
  • 1
blue
  • 7,175
  • 16
  • 81
  • 179

1 Answers1

0

In a collectionView the indexPath used is not Row and Section but Item and Section. Init your indexPath using:

IndexPath(item: itemToSelect, section: 0)

where itemToSelect is an Int with the item you want and you should be able to select the item you want.

Ben Ong
  • 913
  • 1
  • 10
  • 25
  • I tried that but it's not working, I get crash and the error any time I put in a section other than 0: *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'attempt to scroll to invalid index path: {length = 2, path = 1 - 1}' *** First throw call stack: – blue Dec 07 '16 at 01:40
  • That was an example, if your collection view only have ONE section then requesting and indexPath with section 1 instead of 0 will cause that error – Ben Ong Dec 07 '16 at 01:42
  • Ok thank you, I understand what is happening now but it isn't working, meaning it isn't selecting the MSSticker. Apparently selecting the collection view item does not mean selecting the sticker I will edit my question – blue Dec 07 '16 at 01:48