標籤:error ant 效果 amp event activate round like vat
iOS12 的SiriKit添加了新特性shortcuts,相當於玩電腦時使用者佈建快速鍵一個道理,比如我設定ctrl+f10為開啟記事本,設定成功後,我每次直接按ctrl+f10都可以快速開啟記事本。
shortcuts這次有兩種用法,第一種為設定快捷語(shortcut,下同)後,通過Siri直接回到應用,在回到應用時可以擷取設定快捷語時所攜帶資料,可依據該資料或不依據該資料自動進行下一步操作。
第二種用法為設定擴充頁面,不進入app以完成應用的簡單操作功能,如:發資訊/下單等。
今天先簡單介紹一下第二種用法,先看一下效果,如:
建立個SIngle View APP,命名:GotoSiri,語言為:Objective-C
再在File->New->Target->Intents Extension ,記得勾選include UI Extension,後期需要顯示擴充頁面。命名:Ticket,建立完成後需點擊兩次Activate。
工程目錄中出現如下兩個檔案夾:
接下來需要建立intents.intentdefinition檔案,看名字像自訂意圖,其實很雞肋。
New File->SiriKit Intent Definition File
新添加一個名為Test的Intent,建立好後運行一次程式,再點擊Test,在標註區會看到剛才設定好的意圖檔案名稱TestIntent,點擊右側箭頭會進入TestIntent.h標頭檔中,後期用這個自訂的TestIntent意圖時需要引入的標頭檔。
在ViewController.m檔案中,引入“TestIntent.h”和<Intents/Intents.h>兩個標頭檔。
#import "ViewController.h"#import "TestIntent.h"#import <Intents/Intents.h>@interface ViewController ()<TestIntentHandling, INUIAddVoiceShortcutViewControllerDelegate>@property(nonatomic,strong) INUIAddVoiceShortcutViewController *customShortCutViewController;@property(nonatomic,strong) TestIntent *testIntent;@property(nonatomic,strong) TestIntentResponse *testIntentResponse;@property(nonatomic,strong) INInteraction *interaction;@property(nonatomic,strong) INShortcut *shortcut;@end@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. self.title = @"SiriTest"; if (@available(iOS 10.0, *)) { [INPreferences requestSiriAuthorization:^(INSiriAuthorizationStatus status) { switch (status) { case INSiriAuthorizationStatusNotDetermined: NSLog(@"使用者尚未對該應用程式作出選擇。"); break; case INSiriAuthorizationStatusRestricted: NSLog(@"此應用程式無權使用Siri服務"); break; case INSiriAuthorizationStatusDenied: NSLog(@"使用者已明確拒絕此應用程式的授權"); break; case INSiriAuthorizationStatusAuthorized: NSLog(@"使用者可以使用此應用程式的授權"); break; default: break; } }]; } UIButton *_addSiriBtn = [[UIButton alloc] initWithFrame:CGRectMake(30, 151, 200, 50)]; [_addSiriBtn setTitle:@"Add to Siri(Intent)" forState:UIControlStateNormal]; [_addSiriBtn setTitleColor:UIColor.blueColor forState:UIControlStateNormal]; [_addSiriBtn addTarget:self action:@selector(buildShortcutInCurrentViewController) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:_addSiriBtn];}-(void)buildShortcutInCurrentViewController{ self.testIntent = [[TestIntent alloc] init]; self.testIntent.ticket = @"深圳灣體育館王力宏演唱會"; self.testIntent.number = [NSNumber numberWithInteger:2]; self.testIntent.suggestedInvocationPhrase = @"買票"; self.interaction = [[INInteraction alloc] initWithIntent:self.testIntent response:nil]; [self.interaction donateInteractionWithCompletion:^(NSError * _Nullable error) { if(error) { NSLog(@"%@",error); } else { NSLog(@"donate success"); } }]; INShortcut *shortCut = [[INShortcut alloc] initWithIntent:self.testIntent]; self.customShortCutViewController = [[INUIAddVoiceShortcutViewController alloc] initWithShortcut:shortCut]; self.customShortCutViewController.delegate = self; [self presentViewController:self.customShortCutViewController animated:YES completion:nil];}-(void)addVoiceShortcutViewControllerDidCancel:(INUIAddVoiceShortcutViewController *)controller{ [controller dismissViewControllerAnimated:YES completion:nil];}-(void)addVoiceShortcutViewController:(INUIAddVoiceShortcutViewController *)controller didFinishWithVoiceShortcut:(INVoiceShortcut *)voiceShortcut error:(NSError *)error{ [controller dismissViewControllerAnimated:YES completion:nil];}- (void)handleTest:(nonnull TestIntent *)intent completion:(nonnull void (^)(TestIntentResponse * _Nonnull))completion { NSString *ticket = intent.ticket; self.testIntentResponse = [TestIntentResponse successIntentResponseWithTicket:ticket]; completion(self.testIntentResponse);}-(void)confirmTest:(nonnull TestIntent *)intent completion:(nonnull void (^)(TestIntentResponse * _Nonnull))completion{ NSString *ticket = intent.ticket; self.testIntentResponse = [TestIntentResponse successIntentResponseWithTicket:ticket]; completion(self.testIntentResponse);}@end
千萬別忘記修改三個Info.plist檔案
GotoSiri中的info.plist,
Ticket中的info.plist,
TicketUI中的info.plist,
在IntentHandler.m檔案中:
#import "IntentHandler.h"#import "TestIntent.h"@interface IntentHandler ()<TestIntentHandling>@end@implementation IntentHandler- (id)handlerForIntent:(INIntent *)intent { // This is the default implementation. If you want different objects to handle different intents, // you can override this and return the handler you want for that particular intent. return self;}- (void)handleTest:(TestIntent *)intent completion:(void (^)(TestIntentResponse * _Nonnull))completion { if(intent.number == 0) { completion([TestIntentResponse failureIntentResponseWithTicket:intent.ticket]); } completion([TestIntentResponse successIntentResponseWithTicket:intent.ticket]);}-(void)confirmTest:(TestIntent *)intent completion:(void (^)(TestIntentResponse * _Nonnull))completion{ completion([[TestIntentResponse alloc] initWithCode:TestIntentResponseCodeReady userActivity:nil]);}@end
在TicketUI的MainInterface.storyboard中畫個簡單介面
IntentViewController.m中:
#import "IntentViewController.h"#import <Intents/Intents.h>#import "TestIntent.h"// As an example, this extension‘s Info.plist has been configured to handle interactions for INSendMessageIntent.// You will want to replace this or add other intents as appropriate.// The intents whose interactions you wish to handle must be declared in the extension‘s Info.plist.// You can test this example integration by saying things to Siri like:// "Send a message using <myApp>"@interface IntentViewController ()@property (weak, nonatomic) IBOutlet UILabel *testlabel;@end@implementation IntentViewController- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view.}#pragma mark - INUIHostedViewControlling// Prepare your view controller for the interaction to handle.- (void)configureViewForParameters:(NSSet <INParameter *> *)parameters ofInteraction:(INInteraction *)interaction interactiveBehavior:(INUIInteractiveBehavior)interactiveBehavior context:(INUIHostedViewContext)context completion:(void (^)(BOOL success, NSSet <INParameter *> *configuredParameters, CGSize desiredSize))completion { // Do configuration here, including preparing views and calculating a desired size for presentation. TestIntent *intent = (TestIntent *)interaction.intent; self.testlabel.text = [NSString stringWithFormat:@"購買%@張%@門票",intent.number,intent.ticket]; if (completion) { completion(YES, parameters, [self desiredSize]); } if(interaction.intentHandlingStatus == INIntentHandlingStatusSuccess) { self.testlabel.text = @"###123###"; }}- (CGSize)desiredSize { CGSize customSize = [self extensionContext].hostedViewMaximumAllowedSize; customSize.height = 200.0; return customSize;}@end
運行程式, 即可查看效果,此為原著,轉寄請標明出處。
iOS12 SiriKit新特性 shortcuts(一)(Objective-C版本)