Trigger tap on MSSticker or view programmatically?

949 views Asked by At

Alright, I have looked at How to trigger tap gesture recognizer of UIView programmatically and similar questions but cant find what I am looking for. I am building an iMessage app extension, and need too programmatically trigger a tap event on an MSSticker.

I have made custom MSStickerViews with the following class that detects when it has been pressed and/or tapped, then triggers another function, however I do not know how to actually SIMULATE these taps so that the sticker will be put in the entry field:

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

The reason why just calling one of the tap functions above won't work is I don't need to trigger any certain function with the tap - I just need to create a fake tap on the MSSticker within the MSStickerView so it will be put in the entry field. I have no idea how to do this.

I create my MSStickerViews like this and put them in a collection view, but programmatically tapping the collection view cell does nothing (Ive tried):

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

I have a feeling maybe something like (pseudo code)

starterPack[1].sendActionForEvent(UIEvent.Tap)

is correct, but the MSStickerView doesn't have .sendActionForEvent

I am desperate. How can I create a fake tap?

2

There are 2 answers

4
shallowThought On

You have to create a MSMessage, which you than can insert to your current MSConversation.

conversation.insert(message) { error in
    // handle error
}

See Apples sample code.

1
Jeff Sinckler On

To clarify, you have a UICollectionView where you are displaying a bunch of UICollectionViewCell's, each of which have an MSStickerView. I am going to move forward assuming this is right.

You're objective is, when a user taps on one of those collection view cells, you insert the sticker into the message box so that when the user taps the send button, the sticker is sent, correct?

In that scenario, what I would do is maintain a reference to the MSSticker in your UICollectionViewCell subclass (assuming you have a subclass. If you don't, I suggest making one for your purposes). Then, when a user taps a cell and your didSelectCellAt method gets called, you can grab the MSSticker from that cell and insert it into your message.

Hope that makes sense