I have added extension to app(as per apple documentation) but intent handler class is not responding with my commands. what i am missing don't no.Please help me ,How can i add siri to my app.
// reslove
- (void)resolveContactsForStartAudioCall:(INStartAudioCallIntent *)intent
withCompletion:(void (^)(NSArray<INPersonResolutionResult *> *resolutionResults))completion{
NSArray *contacts;
NSArray * contacts1;
INPersonResolutionResult* result = nil;
if (contacts == intent.contacts) {
for (INPerson *contact in contacts) {
contacts1 = [self contactsMatchingName:contact.displayName];
switch (contacts1.count) {
case 1:
result = [contacts objectAtIndex:0];
[INPersonResolutionResult successWithResolvedPerson:[contacts1 objectAtIndex:0]];
break;
case 0:
result = [INPersonResolutionResult unsupported];
break;
default:
result = [ INPersonResolutionResult disambiguationWithPeopleToDisambiguate:contacts1];
break;
}
}
completion(contacts1);
}else{
result = [INPersonResolutionResult needsValue];
}
}
// confirmation method
- (void)confirmStartAudioCall:(INStartAudioCallIntent *)intent
completion:(void (^)(INStartAudioCallIntentResponse *response))completion{
INStartAudioCallIntentResponse *result = nil;
if (![[NSUserDefaults standardUserDefaults]objectForKey:#"isSignedIn"]) {
result = [[INStartAudioCallIntentResponse alloc]initWithCode:INStartAudioCallIntentResponseCodeReady userActivity:nil];
completion(result);
}else{
NSUserActivity *activity = [[NSUserActivity alloc]initWithActivityType:#"reLogin"];
result = [[INStartAudioCallIntentResponse alloc]initWithCode:INStartAudioCallIntentResponseCodeFailure userActivity:activity];
completion(result);
}
}
Here are a few resources to get you started.
Guides and Documentation
SiriKit Programming Guide
Intents Framework
IntentsUI Framework
Sample Code
UnicornChat Sample App
Videos (from WWDC 2016)
Introducing SiriKit
Extending your app with SiriKit
Related
I am trying to integrate Hyperpay payment into React Native project and I have problems with objective-c, I followed an article and found many issues and with searching, I solve them, but still two issues I can't solve because I am not familiar with objective-c
Issue 1,
No known class method for selector 'presentCheckoutForSubmittingTransactionCompletionHandler:cancelHandler:'
Issue 2,
No known class method for selector 'dismissCheckoutAnimated:completion:'
I am sorry if my code is long but I don't to miss something
// RCTCalendarModule.m
#import "HyperPay.h"
#import "UIKit/UIKit.h"
#import <OPPWAMobile/OPPWAMobile.h>
#implementation HyperPay{
RCTResponseSenderBlock onDoneClick;
RCTResponseSenderBlock onCancelClick;
UIViewController *rootViewController;
NSString *isRedirect;
OPPPaymentProvider *provider;
}
// To export a module named RCTCalendarModule
RCT_EXPORT_METHOD(openHyperPay:(NSDictionary *)indic createDialog:(RCTResponseSenderBlock)doneCallback createDialog:(RCTResponseSenderBlock)cancelCallback) {
onDoneClick = doneCallback;
onCancelClick = cancelCallback;
NSArray *events = #[];
if ([indic[#"is_sandbox"] isEqualToString:#"1"]) {
provider = [OPPPaymentProvider paymentProviderWithMode:OPPProviderModeTest];
} else {
provider = [OPPPaymentProvider paymentProviderWithMode:OPPProviderModeLive];
}
OPPCheckoutSettings *checkoutSettings = [[OPPCheckoutSettings alloc] init];
// Set available payment brands for your shop
checkoutSettings.paymentBrands = #[#"VISA", #"MASTER"];
// Set shopper result URL
checkoutSettings.shopperResultURL = #"com.simicart.enterprise.payments://result";
OPPCheckoutProvider *checkoutProvider = [OPPCheckoutProvider checkoutProviderWithPaymentProvider:provider checkoutID:indic[#"checkoutId"]
settings:checkoutSettings];
dispatch_async(dispatch_get_main_queue(), ^{
[OPPCheckoutProvider presentCheckoutForSubmittingTransactionCompletionHandler:^(OPPTransaction * _Nullable transaction, NSError * _Nullable error) {
if (error) {
// Executed in case of failure of the transaction for any reason
if (isRedirect && ![isRedirect isEqualToString:#"1"]) {
onCancelClick(#[#"cancel", events]);
}
} else if (transaction.type == OPPTransactionTypeSynchronous) {
// Send request to your server to obtain the status of the synchronous transaction
// You can use transaction.resourcePath or just checkout id to do it
NSDictionary *responeDic = #{#"resourcePath" : transaction.resourcePath};
onDoneClick(#[responeDic, events]);
NSLog(#"%#", transaction.resourcePath);
} else {
// The SDK opens transaction.redirectUrl in a browser
// See 'Asynchronous Payments' guide for more details
}
} cancelHandler:^{
onCancelClick(#[#"cancel", events]);
// Executed if the shopper closes the payment page prematurely
}];
});
}
- (instancetype)init{
self = [super init];
if (self) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(getStatusOder:) name:#"getStatusOrder" object:nil];
}
return self;
}
- (void)getStatusOder:(NSNotification*)noti{
[OPPCheckoutProvider dismissCheckoutAnimated:YES completion:^{
isRedirect = #"1";
NSURL *url = noti.object;
NSString *urlString = [url absoluteString];
NSLog(#"%#", urlString);
if (![urlString isEqualToString:#"com.simicart.enterprise.payments://result"]) {
NSArray *events = #[];
NSDictionary *responeDic = #{#"url" : urlString};
onDoneClick(#[responeDic, events]);
}
}];
}
#end
I added NSLog(..) statements on each method but it was not going to the handle send message delegate. I need to get some message from Siri to do some tasks. Also, is there any way to get the date/time from speech with INSentMessageDomiain
import "IntentHandler.h"
// As an example, this class is set up to handle Message intents.
// You will want to replace this or add other intents as appropriate.
// The intents you wish to handle must be declared in the extension's Info.plist.
// You can test your example integration by saying things to Siri like:
// "Send a message using <myApp>"
// "<myApp> John saying hello"
// "Search for messages in <myApp>"
#interface IntentHandler () <INSendMessageIntentHandling, INSearchForMessagesIntentHandling, INSetMessageAttributeIntentHandling>
{
NSString *resName;
}
#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.
if ([intent isKindOfClass:[INSendMessageIntent class]]) {
}
return self;
}
#pragma mark - INSendMessageIntentHandling
// Implement resolution methods to provide additional information about your intent (optional).
- (void)resolveRecipientsForSendMessage:(INSendMessageIntent *)intent withCompletion:(void (^)(NSArray<INPersonResolutionResult *> *resolutionResults))completion {
// If no recipients were provided we'll need to prompt for a value.
NSMutableArray<INPersonResolutionResult *> *resolutionResults = [NSMutableArray array];
//NSArray<INPerson *> *recipients = intent.recipients;
[resolutionResults addObject:[INPersonResolutionResult notRequired]];
completion(resolutionResults);
}
- (void)resolveContentForSendMessage:(INSendMessageIntent *)intent withCompletion:(void (^)(INStringResolutionResult *resolutionResult))completion {
NSString *text = intent.content;
if (text.length == 0) {
completion([INStringResolutionResult needsValue]);
}
else {
completion([INStringResolutionResult successWithResolvedString:text]);
}
}
// Handle the completed intent (required).
- (void)handleSendMessage:(INSendMessageIntent *)intent completion:(void (^)(INSendMessageIntentResponse *response))completion {
//Implement your application logic to send a message here.
NSUserActivity *userActivity = [[NSUserActivity alloc] initWithActivityType:NSStringFromClass([INSendMessageIntent class])];
INSendMessageIntentResponse *response = [[INSendMessageIntentResponse alloc]initWithCode:INSendMessageIntentResponseCodeSuccess userActivity:userActivity];
completion(response);
}
I am working on an existing objective c project , While reading Address Book UI Framework Reference for iOS i found the below classes have deprecated in iOS 9 .
( ABUnknownPersonViewController , ABPersonViewController , ABPeoplePickerNavigationController, ABNewPersonViewController )
What is the replacement of this .? Where i can find some document related this . any help appreciated . Thanks in advance .
The AddressBookUI framework has been deprecated in iOS 9, so better you should use ContactsUI Framework.
It has many new features including all the features of AddressBookUI framework.
So, in case if you are targeting the iOS 9 specifically then you should go for ContactsUI Framework.
To check that AddressBookUI framework is available for specific iOS version you can do the following:
if ([CNContactStore class]) {
CNContactStore *store = [CNContactStore new];
//...
} else {
// Fallback to old framework
}
Here is the complete code for that:
- (void) contactScan
{
if ([CNContactStore class]) {
//ios9 or later
CNEntityType entityType = CNEntityTypeContacts;
if( [CNContactStore authorizationStatusForEntityType:entityType] == CNAuthorizationStatusNotDetermined)
{
CNContactStore * contactStore = [[CNContactStore alloc] init];
[contactStore requestAccessForEntityType:entityType completionHandler:^(BOOL granted, NSError * _Nullable error) {
if(granted){
[self getAllContact];
}
}];
}
else if( [CNContactStore authorizationStatusForEntityType:entityType]== CNAuthorizationStatusAuthorized)
{
[self getAllContact];
}
}
}
-(void)getAllContact
{
if([CNContactStore class])
{
//iOS 9 or later
NSError* contactError;
CNContactStore* addressBook = [[CNContactStore alloc]init];
[addressBook containersMatchingPredicate:[CNContainer predicateForContainersWithIdentifiers: #[addressBook.defaultContainerIdentifier]] error:&contactError];
NSArray * keysToFetch =#[CNContactEmailAddressesKey, CNContactPhoneNumbersKey, CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPostalAddressesKey];
CNContactFetchRequest * request = [[CNContactFetchRequest alloc]initWithKeysToFetch:keysToFetch];
BOOL success = [addressBook enumerateContactsWithFetchRequest:request error:&contactError usingBlock:^(CNContact * __nonnull contact, BOOL * __nonnull stop){
[self parseContactWithContact:contact];
}];
}
}
- (void)parseContactWithContact :(CNContact* )contact
{
NSString * firstName = contact.givenName;
NSString * lastName = contact.familyName;
NSString * phone = [[contact.phoneNumbers valueForKey:#"value"] valueForKey:#"digits"];
NSStrubg * email = [contact.emailAddresses valueForKey:#"value"];
NSArray * addrArr = [self parseAddressWithContac:contact];
}
- (NSMutableArray *)parseAddressWithContac: (CNContact *)contact
{
NSMutableArray * addrArr = [[NSMutableArray alloc]init];
CNPostalAddressFormatter * formatter = [[CNPostalAddressFormatter alloc]init];
NSArray * addresses = (NSArray*)[contact.postalAddresses valueForKey:#"value"];
if (addresses.count > 0) {
for (CNPostalAddress* address in addresses) {
[addrArr addObject:[formatter stringFromPostalAddress:address]];
}
}
return addrArr;
}
Just make sure that you ask the permission to read the contacts from device.
Reference link: https://gist.github.com/willthink/024f1394474e70904728
Updated:
For replacement for AddressBookUI you need to use CNContactPickerViewController. You can check the delegate methods which can be used to pickup the one or multiple contacts at a time.
This will present a inbuilt UIViewController with all the contacts and you need to implement the delegate methods of it!
To select one contact:
contactPicker:didSelectContact:
To select multiple (New Feature):
contactPicker:didSelectContacts:
CNContactPickerDelegate reference: https://developer.apple.com/library/ios/documentation/ContactsUI/Reference/CNContactPickerDelegate_Protocol/
Apple has introduced new framework for this for iOS9 and above please fine below link Link
Edit:
one more link :Link2
I recently started working with UIActivity to share my app to the world, but I have few problems. First, I didn't find how to set the subject of my email. Is there any way? Second, when I set the body text of my email, there is a extra "enter" (first line of the email is blank and my text starts at the second line). Here's the code:
NSMutableArray *array = [[NSMutableArray alloc] initWithObjects: #"Test", nil];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc]
initWithActivityItems:array applicationActivities:nil];
And in the email, it shows that:
"
Test
"
Third: is there a way to know which sharing method has been selected? Because I want to include a hashtag in my post when the user shares on twitter, but now it gets integrated in the email also, which obviously doesn't make sense.
Thanks!
For adding subject to the email using UIActivityViewController on iOS6, this is the best solution that anyone can use.. All you have to do is call the following while initializing UIActivityViewController.
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:applicationActivities];
[activityViewController setValue:#"My Subject Text" forKey:#"subject"];
And your UIActivityViewController is populated with a subject.
In iOS7, this is possible by using -
activityViewController:subjectForActivityType:
When posting an item the service may provide for a separate subject
field and data field, such as an email message. Implement this method
if you wish to provide a subject field for services that support one.
Check - https://developer.apple.com/library/ios/documentation/uikit/reference/UIActivityItemSource_protocol/Reference/Reference.html#//apple_ref/occ/intfm/UIActivityItemSource/activityViewController:subjectForActivityType:
1 and 2: How do I set recipients for UIActivityViewController in iOS 6?
Although both provided methods are a bit of a hack, especially the first one, it is possible.
3: it is possible to share different content on different services, but the number of items and their types should be the same (but it is not a limitation, really, as you can return nil for items you don't need on particular service). You have to create sharing items after the service was selected using UIActivityItemSource protocol
Code I use:
Show UIActivityViewController with the current controller as provider of all items (it should have in .h file):
const int numberOfSharedItems = 5;
- (IBAction)shareAction:(id)sender
{
NSMutableArray *shareItems = [NSMutableArray new];
while ([shareItems count] < numberOfSharedItems)
[shareItems addObject: self];
UIActivityViewController *shareController =
[[UIActivityViewController alloc]
// actual items are prepared by UIActivityItemSource protocol methods below
initWithActivityItems: shareItems
applicationActivities :nil];
shareController.excludedActivityTypes = #[UIActivityTypeMessage, UIActivityTypePrint, UIActivityTypeCopyToPasteboard, UIActivityTypeAssignToContact, UIActivityTypeSaveToCameraRoll];
[self presentViewController: shareController animated: YES completion: nil];
}
Make placeholders for items that will be shared:
-(id)activityViewControllerPlaceholderItem:(UIActivityViewController *)activityViewController
{
static UIActivityViewController *shareController;
static int itemNo;
if (shareController == activityViewController && itemNo < numberOfSharedItems - 1)
itemNo++;
else {
itemNo = 0;
shareController = activityViewController;
}
switch (itemNo) {
case 0: return #""; // intro in email
case 1: return #""; // email text
case 2: return [NSURL new]; // link
case 3: return [UIImage new]; // picture
case 4: return #""; // extra text (via in twitter, signature in email)
default: return nil;
}
}
Make actual items that will be shared, differently for different services:
-(id)activityViewController:(UIActivityViewController *)activityViewController itemForActivityType:(NSString *)activityType
{
// the number of item to share
static UIActivityViewController *shareController;
static int itemNo;
if (shareController == activityViewController && itemNo < numberOfSharedItems - 1)
itemNo++;
else {
itemNo = 0;
shareController = activityViewController;
}
NSString *shareText = [self shareText]; // whatever you fancy
NSURL *shareURL = [self shareURL];
// twitter
if ([activityType isEqualToString: UIActivityTypePostToTwitter])
switch (itemNo) {
case 0: return nil;
case 1: return shareText; // you can change text for twitter, I add $ to stock symbol inside shareText here, e.g. Hashtags can be added too
case 2: return shareURL;
case 3: return nil; // no picture
case 4: return #"via #YourApp";
default: return nil;
}
// email
else if ([activityType isEqualToString: UIActivityTypeMail])
switch (itemNo) {
case 0: return #"Hi!\r\n\r\nI used YourApp\r\n";
case 1: return shareText;
case 2: return shareURL;
case 3: return nil; // no picture
case 4: return [#"\r\nCheck it out.\r\n\r\nCheers\r\n" stringByAppendingString: [self userName]];
default: return nil;
}
else // Facebook or something else in the future
switch (itemNo) {
case 0: return nil;
case 1: return shareText;
case 2: return shareURL;
case 3: return [self shareImage];
case 4: return nil;
default: return nil;
}
}
u can simply create a class as follows :
#interface MYNActivityProvider : UIActivityItemProvider <UIActivityItemSource>
#end
// implementation
- (id) activityViewController:(UIActivityViewController *)activityViewController
itemForActivityType:(NSString *)activityType
{
if ( [activityType isEqualToString:UIActivityTypePostToTwitter] ) {
return stringToPost;
}
if ( [activityType isEqualToString:UIActivityTypePostToFacebook] ) {
return stringToPost;
}
if ( [activityType isEqualToString:UIActivityTypeMessage] ) {
return #"SMS message text";
}
if ( [activityType isEqualToString:UIActivityTypeMail] ) {
return #"Email text here!";
}
if ( [activityType isEqualToString:#"Custom"] ) {
return #"app custom text";
}
return nil;
}
You might want to try OvershareKit.
We are frequently asked why someone would use OvershareKit instead of UIActivityViewController (UIAVC) and UIActivity. UIAVC is great for apps that know they’ll never have a need for any of the following:
Never need to integrate with more than one or two third party services.
Never need to tweak the UI for the activity sheet and sharing screens.
Never care to provide separate, media-specific content for each sharing type (email versus SMS, etc.)
Never need to have multiple items such as a Copy Text versus a Copy Link in the same sheet.
Don't mind that all non-system-provided activities get stuck with boring monochromatic icons.
Your situation is (3) - a need to care about different content for different sharing type.
i want to migrate my existing app to iCloud.
in my attempt to learn what to do, i have tried a sample app that has worked as described in the demo (as seen in lecture 17 of the iTunes stanford university course).
can someone who has had this problem help me diagnose what step i messed up to cause the following to fail? is this just telling me basically that there's no data to query? or is there something else going on that i haven't properly configured?
i am getting the following in my console (which occurs in the code below immediately after i call [self.iCloudQuery startQuery];
item update error: 0, Error Domain=LibrarianErrorDomain Code=10 "The operation couldn’t be completed.
(LibrarianErrorDomain error 10 - Unable to configure the collection.)" UserInfo=0x11ee00 {NSDescription=Unable to
configure the collection.}
i created a development provisioning profile that has iCloud turned on on iTunes connect.
i turned on entitlements. here are the contents:
the code is straight from the Stanford University iTunes lectures:
#import "DocumentViewController.h"
#interface DocumentViewController ()
#property (strong, nonatomic) NSArray* documents; // of NSURLs
#property (strong, nonatomic) NSMetadataQuery* iCloudQuery;
#end
#implementation DocumentViewController
#synthesize documents = _documents;
#synthesize iCloudQuery = _iCloudQuery;
- (void)setDocuments:(NSArray*)documents {
// always sort documents alphabetically
documents
= [documents sortedArrayUsingComparator:^NSComparisonResult(NSURL* url1, NSURL* url2) {
return [[url1 lastPathComponent] caseInsensitiveCompare:[url2 lastPathComponent]];
}];
if (![documents isEqualToArray:_documents])
{
_documents = documents;
[self.tableView reloadData];
}
}
- (NSMetadataQuery*)iCloudQuery {
if (!_iCloudQuery)
{
_iCloudQuery = [[NSMetadataQuery alloc] init];
_iCloudQuery.searchScopes
= [NSArray arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope];
_iCloudQuery.predicate
= [NSPredicate predicateWithFormat:#"%K like '*'", NSMetadataItemFSNameKey];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(processCloudQueryResults:)
name:NSMetadataQueryDidFinishGatheringNotification
object:_iCloudQuery];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(processCloudQueryResults:)
name:NSMetadataQueryDidUpdateNotification
object:_iCloudQuery];
}
return _iCloudQuery;
}
#pragma mark - private implementation
- (NSURL*)iCloudURL {
return [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
}
- (NSURL*)iCloudDocumentsURL {
return [self.iCloudURL URLByAppendingPathComponent:#"Documents"];
}
- (NSURL*)filePackageURLForCloudURL:(NSURL*)url
{
if ([url.path hasPrefix:self.iCloudDocumentsURL.path])
{
NSArray* iCloudDocumentsURLComponents = self.iCloudDocumentsURL.pathComponents;
NSArray* urlComponents = url.pathComponents;
if (iCloudDocumentsURLComponents.count < urlComponents.count)
{
NSRange newRange = NSMakeRange(0, iCloudDocumentsURLComponents.count+1);
urlComponents = [urlComponents subarrayWithRange:newRange];
url = [NSURL fileURLWithPathComponents:urlComponents];
}
}
return url;
}
- (void)processCloudQueryResults:(NSNotification*)notification
{
[self.iCloudQuery disableUpdates];
NSMutableArray* documents = [NSMutableArray array];
NSUInteger resultCount = self.iCloudQuery.resultCount;
for (NSUInteger i = 0; i < resultCount ; ++i)
{
NSMetadataItem* item = [self.iCloudQuery resultAtIndex:i];
NSURL* url = [item valueForAttribute:NSMetadataItemURLKey];
url = [self filePackageURLForCloudURL:url];
[documents addObject:url];
}
self.documents = documents;
[self.iCloudQuery enableUpdates];
}
#pragma mark - overrides
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
if (![self.iCloudQuery isStarted])
[self.iCloudQuery startQuery];
[self.iCloudQuery enableUpdates];
}
- (void)viewWillDisappear:(BOOL)animated {
[self.iCloudQuery disableUpdates];
[super viewWillDisappear:animated];
}
for anyone else running into this … apparently, this is the error that occurs when you haven't enabled iCloud on the device on which you are testing. once i enabled iCloud on the device, the error stopped occurring in my log.
and so now i know what error to check for in order to present the user with a dialog saying "connecting to iCloud won't work until you sign up for iCloud in the system preferences".