iOS 10 iMessage 贴纸应用中 MSSticker Peels 的回调

Posted

技术标签:

【中文标题】iOS 10 iMessage 贴纸应用中 MSSticker Peels 的回调【英文标题】:Callback for MSSticker Peels in iOS 10 iMessage sticker app 【发布时间】:2016-11-21 08:55:42 【问题描述】:

我正在 ios 10 中试验贴纸 iMessage 应用程序,但在 MSMessagesAppViewController 中的 override func didStartSending(_ message: MSMessage, conversation: MSConversation) 方法遇到问题。当从MSStickerView 上“剥离”贴纸时,我希望在didStartSending 方法上收到某种回调。但似乎情况并非如此。有谁知道这是否是预期的行为和/或是否有另一种方法可以订阅回调这些贴纸何时被剥离、拖动并放入MSConversation?我意识到didStartSending 是为用户点击发送按钮时保留的,但肯定应该有某种方法知道用户何时拖动 MSStickers 而无需将一些 UIView 拖动/矩形读取启发式组合在一起。

消息视图控制器:

class MessagesViewController: MSMessagesAppViewController 

    var nYCStickersBroswerViewController: NYCStickersBroswerViewController!

    override func viewDidLoad() 
        super.viewDidLoad()
        nYCStickersBroswerViewController = NYCStickersBroswerViewController(stickerSize: .regular)
        nYCStickersBroswerViewController.view.frame = self.view.frame

        self.addChildViewController(nYCStickersBroswerViewController)
        nYCStickersBroswerViewController.didMove(toParentViewController: self)
        self.view.addSubview(nYCStickersBroswerViewController.view)

        nYCStickersBroswerViewController.loadStickers()
        nYCStickersBroswerViewController.stickerBrowserView.reloadData()
    

    ...

    override func didStartSending(_ message: MSMessage, conversation: MSConversation) 
        // Called when the user taps the send button.
        print(message) // should this not contain the sticker that is peeled, dragged, and dropped into the conversation?
    

 

贴纸浏览器:

import Foundation
import UIKit
import Messages

class ASSticker: MSSticker 
    var identifier: String?


class NYCStickersBroswerViewController: MSStickerBrowserViewController 

    var stickers = [ASSticker]()

    override func viewDidLoad() 
        super.viewDidLoad()
    

    func changeBrowswerViewBackgroundColor(color: UIColor) 
        stickerBrowserView.backgroundColor = color
    

    func loadStickers() 
        createSticker(name: "***lyn", localizedDescription: "***lyn Bridge Sticker")
        createSticker(name: "liberty", localizedDescription: "Statue of Liberty Sticker")
        createSticker(name: "love", localizedDescription: "I Love New York Sticker")
        createSticker(name: "mets", localizedDescription: "New York Mets Sticker")
        createSticker(name: "rangers", localizedDescription: "New York Rangers Sticker")
        createSticker(name: "subway", localizedDescription: "New York City MTA Subway Train Sticker")
    

    func createSticker(name: String, localizedDescription: String) 
        guard let stickerPath = Bundle.main.pathForResource(name, ofType: "png") else 
            print("Call ae cab, you're intoxicated.")
            return
        
        let stickerURL = URL(fileURLWithPath: stickerPath)
        let sticker: ASSticker
        do 
            try sticker = ASSticker(contentsOfFileURL: stickerURL, localizedDescription: localizedDescription)
            sticker.identifier = "something unique"
            stickers.append(sticker)
         catch 
            print("Call a cab, you're intoxicated.")
        
    

    override func numberOfStickers(in stickerBrowserView: MSStickerBrowserView) -> Int 
        return self.stickers.count
    
    override func stickerBrowserView(_ stickerBrowserView: MSStickerBrowserView, stickerAt index: Int) -> MSSticker 
        return self.stickers[index]
    


【问题讨论】:

嘿,你有没有让这个工作?我也有同样的问题 下面的答案是很好的解决方法,但我还没有想出使用股票 MSStickerBrowserViewController 的解决方案。 【参考方案1】:

这是一个子类和委托,它将与MSStickerView 用于选择和剥离交互的点击和长按手势识别器相关联。如果MSStickerView 的实现发生变化,这可能不再提供事件,但不应崩溃。

import UIKit
import Messages

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

    func didLongPress(longPressGestureRecognizer: UILongPressGestureRecognizer) 
        if longPressGestureRecognizer.state == .Began 
            delegate?.stickerViewDidPeel(self)
        
    

【讨论】:

嘿,你会如何使用它,即如果我有贴纸,我如何在我的课堂上使用这些回调函数? 一个使用示例会很有帮助 很好的解决方案! @skyguy 使用,只需将您的 MSStickerView 替换为 InstrumentedStickerView 并确保将委托属性设置为实现 InstrumentedStickerViewDelegate 的类:stickerView.delegate = self 如果我只想在特定条件下“窃取”手势,我必须将手势转发到哪里才能启用选择和剥离交互? 在贴纸上双击会使应用程序以展开模式挂起。有没有人可以帮忙?【参考方案2】:

这是贴纸剥离和点击事件的解决方法,不能保证会插入特定贴纸,而是此类数据点的近似值 - 您必须使用 MSStickerView 的子类。此解决方案不是面向未来的,但目前适用于恕我直言,因此我欢迎其他想法。

import UIKit
import Messages

class CustomStickerView : MSStickerView
    class GestureRecognizerReceiver : NSObject, UIGestureRecognizerDelegate
        func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool 
            return true
        
    
    let _recognizerDelegate = GestureRecognizerReceiver()

    weak var _recognizer: UITapGestureRecognizer? = nil
    func setupTapRecognizer()
        if _recognizer == nil 
            let r = UITapGestureRecognizer(target: self, action: #selector(_customTapReceived))
            r.cancelsTouchesInView = false
            r.delegate = _recognizerDelegate
            addGestureRecognizer(r)
            _recognizer = r
    


    func _customTapReceived()
        if let s = sticker
            Analytics.shared.reportEvent(name: "Sticker Inserted", description: s.localizedDescription)
        
    

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) 
        super.touchesBegan(touches, with: event)
        if let s = sticker
            Analytics.shared.reportEvent(name: "Sticker Peeled", description: s.localizedDescription)
        

    

用法:

let sv = CustomStickerView(frame: _stickerViewHolder.bounds, sticker: sticker)
sv.setupTapRecognizer()
_stickerViewHolder.addSubview(sv)
sv.startAnimating()

【讨论】:

以上是关于iOS 10 iMessage 贴纸应用中 MSSticker Peels 的回调的主要内容,如果未能解决你的问题,请参考以下文章

为 iMessage 动态加载贴纸

禁止用户从 iMessage 扩展程序/应用程序下载贴纸

iMessage 中的贴纸数量

如何本地化 iMessage 贴纸?

如何像在 iOS 中为 iMessage 一样为 Android 创建贴纸包?

提交 iMessage 贴纸包需要 iPad 截图吗?