具有多个快捷方式(NSUserActivity)时,siri快捷方式按钮(INUIAddVoiceShortcutButton)显示错误的标题

时间:2018-09-15 08:15:32

标签: ios swift ios12 sirishortcuts

我的应用程序中有2个siri快捷方式。 我使用NSUserActivity捐赠这些快捷方式。我还在info.plist中创建了2个NSUserActivityTypes。

有2个用于处理这些快捷方式的视图控制器(1个视图控制器对应1个快捷方式)。

如果我从1个视图控制器中添加1个siri快捷方式,然后转到第2个视图控制器,则第2个视图控制器上的本机siri快捷方式按钮(INUIAddVoiceShortcutButton)会自动选择第一个快捷方式(由第一个视图控制器创建)并显示使用建议的短语“添加到Siri”,而不显示“添加到Siri”按钮。我再次检查了每个NSUserActivity的标识符是否不同,但仍然以某种方式选择了错误的快捷方式。

View Controller 1:

let userActivity = NSUserActivity(activityType: "com.activity.type1")
userActivity.isEligibleForSearch = true
userActivity.isEligibleForPrediction = true
userActivity.title = shortcut.title
userActivity.suggestedInvocationPhrase = suggestedPhrase

let attributes = CSSearchableItemAttributeSet(itemContentType: kUTTypeItem as String)
attributes.contentDescription = description
userActivity.contentAttributeSet = attributes
let shortcut = INShortcut(userActivity: userActivity)
let siriButton = INUIAddVoiceShortcutButton(style: .whiteOutline)
siriButton.translatesAutoresizingMaskIntoConstraints = false
siriButton.shortcut = shortcut
self.view.addSubview(siriButton)

View Controller 2:

let userActivity2 = NSUserActivity(activityType: "com.activity.type2")
userActivity2.isEligibleForSearch = true
userActivity2.isEligibleForPrediction = true
userActivity2.title = shortcut.title
userActivity2.suggestedInvocationPhrase = suggestedPhrase

let attributes = CSSearchableItemAttributeSet(itemContentType: kUTTypeItem as String)
attributes.contentDescription = description
userActivity2.contentAttributeSet = attributes

let shortcut = INShortcut(userActivity: userActivity2)
let siriButton = INUIAddVoiceShortcutButton(style: .whiteOutline)
siriButton.translatesAutoresizingMaskIntoConstraints = false
siriButton.shortcut = shortcut
self.view.addSubview(siriButton)

当我删除该应用程序并重新安装而不删除手机设置应用程序中的快捷方式时,也会发生类似的事情。

6 个答案:

答案 0 :(得分:3)

似乎是一个IOS错误。我想出了解决此问题的方法。每次用户添加/编辑siri快捷方式时,您都必须创建一个新的siri按钮。在创建siri按钮之前,请执行以下操作

1-通过调用函数从INVoiceShortcutCenter获取所有语音快捷方式。请注意,这是异步发生的,因此您需要花一些时间才能获取数据(例如,在AppDelegate中)。每当用户添加Siri快捷方式(可能在INUIAddVoiceShortcutViewControllerDelegate.addVoiceShortcutViewController(_:didFinishWith:error)方法中)时,您还需要重新加载它。

INVoiceShortcutCenter.shared.getAllVoiceShortcuts  { (voiceShortcutsFromCenter, error) in
    guard let voiceShortcutsFromCenter = voiceShortcutsFromCenter else {
            if let error = error as NSError? {
                os_log("Failed to fetch voice shortcuts with error: %@", log: OSLog.default, type: .error, error)
            }
            return
        }
        self.voiceShortcuts = voiceShortcutsFromCenter
}

2-在View Controller-1中,通过迭代所有语音快捷方式来检查快捷方式是否已添加

let voiceShorcut = voiceShortcuts.first { (voiceShortcut) -> Bool in
    if let activity = voiceShortcut.shortcut.userActivity, activity.activityType == "com.activity.type1" {
        return true
    }
    return false
}

3-如果您的语音快捷方式已注册,则将INShortcut传递到siri按钮,否则请勿进行设置。

if voiceShorcut != nil {
    let shortcut = INShortcut(userActivity: userActivity1)
    siriButton.shortcut = shortcut
} 

在Second View Controller中执行相同的操作。

答案 1 :(得分:3)

这是iOS 12.0错误。 您可以通过使用正确的值更新INUIAddVoiceShortcutButton.voiceShortcut来修复它。 使用KVO观察“ voiceShortcut”属性,并在其更改时为其分配正确的值。

答案 2 :(得分:0)

我只是通过将实现(最初基于soupchef应用程序)更改为苹果(https://developer.apple.com/documentation/sirikit/inuiaddvoiceshortcutbutton)提供的以下代码示例来解决此问题:

编辑:我添加了代码,展示了我如何为UserActivity和自定义Intent快捷方式创建和传递捷径对象(INShortcut)。

Shortcut类是一个枚举,其中包含一个称为intent的计算属性,该属性返回自定义intent的实例化。

private func addShortcutButton(shortcut: Shortcut, parentViewController: UIViewController, shortcutViewControllerDelegate: INUIAddVoiceShortcutViewControllerDelegate) {
    guard let view = parentViewController.view else { return }

    if let intent = shortcut.intent {
        shortcutObject = INShortcut(intent: intent)
    } else if let userActivity = view.userActivity {
        shortcutObject = INShortcut(userActivity: userActivity)
    }

    self.shortcutViewControllerDelegate = shortcutViewControllerDelegate
    addSiriButton(to: shortcutButtonContainer)
}

func addSiriButton(to view: UIView) {
    let button = INUIAddVoiceShortcutButton(style: .whiteOutline)
    button.translatesAutoresizingMaskIntoConstraints = false

    view.addSubview(button)
    view.centerXAnchor.constraint(equalTo: button.centerXAnchor).isActive = true
    view.centerYAnchor.constraint(equalTo: button.centerYAnchor).isActive = true

    button.addTarget(self, action: #selector(addToSiri(_:)), for: .touchUpInside)
}

// Present the Add Shortcut view controller after the
// user taps the "Add to Siri" button.
@objc
func addToSiri(_ sender: Any) {
    guard let shortcutObject = shortcutObject else { return }
    let viewController = INUIAddVoiceShortcutViewController(shortcut: shortcutObject)
    viewController.modalPresentationStyle = .formSheet
    viewController.delegate = shortcutViewControllerDelegate
    parentViewController?.present(viewController, animated: true, completion: nil)
}

答案 3 :(得分:0)

我现在已移至意图设置,我发现即使仅进行一个意图设置并使用 INUIAddVoiceShortcutButton 也无法跟踪我的快捷方式。记录了短语后,它会显示带有短语的“已添加到Siri”。

但是,每次应用重新启动时,都会显示“添加到Siri”按钮,而不是带有录制短语的“添加到Siri”按钮。

我尝试按照Bilal的建议进行操作,尽管我可以看到INVoiceShortcutCenter向我显示了我的快捷方式,但该快捷方式并未将其加载到Siri按钮中。

对于按钮本身,我的代码看起来像这样。

 private func addSiriButton() {
    let addShortcutButton = INUIAddVoiceShortcutButton(style: .blackOutline)
    addShortcutButton.delegate = self

    addShortcutButton.shortcut = INShortcut(intent: engine.intent )
    addShortcutButton.translatesAutoresizingMaskIntoConstraints = false

    siriButtonSubView.addSubview(addShortcutButton)
    siriButtonSubView.centerXAnchor.constraint(equalTo: addShortcutButton.centerXAnchor).isActive = true
    siriButtonSubView.centerYAnchor.constraint(equalTo: addShortcutButton.centerYAnchor).isActive = true

}

我已经实现了所有协议,并且仔细查看了Soup应用程序,但无法确定是什么导致了这种不准确性。

很有趣,即使英国航空公司的应用程序开发人员也放弃了这一点,因为他们的按钮具有完全相同的故障行为。

更新:我已经为Intent构建了另一个测试项目,该项目的实现量最少,并且Add to Siri和Add to Siri可以完美地工作。我猜测到这一点,我自己的应用程序代码库中有某种原因导致了这种不良行为。

更新2 只是想让大家知道我已经解决了该问题。使用Intent可以很好地工作,但是Intents定义文件本身肯定有一点敏感性。我要做的就是创建一个新的意图,然后生成该意图并使其起作用。似乎我的最初意图某种程度上已损坏,但没有错误。在创建另一个意图并重新分配意图处理功能之后,它全部按预期工作。 (双关语意味)

答案 4 :(得分:0)

所以我们不能使用默认的Siri按钮,您必须使用自定义UIButton。 VoiceShortcutsManager类将检查所有语音意图,然后我们可以搜索该列表以检查是否存在一个匹配项(如果是),因此我们建议版本,否则建议添加。

hide_sloution()

然后在您的ViewController中实现

public class VoiceShortcutsManager {

    private var voiceShortcuts: [INVoiceShortcut] = []

    public init() {

        updateVoiceShortcuts(completion: nil)
    }


    public func voiceShortcut(for order: DeviceIntent, powerState: State) -> INVoiceShortcut? {

        for element in voiceShortcuts {

            guard let intent = element.shortcut.intent as? ToggleStateIntent else {
                continue
            }
            let deviceIntent = DeviceIntent(identifier: intent.device?.identifier, display: intent.device?.displayString ?? "")
            if(order == deviceIntent && powerState == intent.state) {
                return element
            }
        }
        return nil
    }


    public func updateVoiceShortcuts(completion: (() -> Void)?) {

        INVoiceShortcutCenter.shared.getAllVoiceShortcuts { (voiceShortcutsFromCenter, error) in
            guard let voiceShortcutsFromCenter = voiceShortcutsFromCenter else {
                if let error = error {
                    print("Failed to fetch voice shortcuts with error: \(error.localizedDescription)")
                }
                return
            }
            self.voiceShortcuts = voiceShortcutsFromCenter
            if let completion = completion {
                completion()
            }
        }
    }

}

此代码是从此网页获得启发/复制的: https://www.nodesagency.com/test-drive-a-siri-shortcuts-intro/

答案 5 :(得分:0)

我解决这个问题的经验有点不同。通过“添加到 Siri”按钮添加的一些意图起作用,调整为“添加到 Siri”,而其他意图则没有。我意识到有效的操作不需要参数。

为暴露参数的意图设置默认值后,这些参数被传递到 INShortcut(然后分配给 INUIAddVoiceShortcutButton),所有按钮都正确更新了它们的状态!