So, in my app, I want to share something using the UIActivityViewController.
To make sure that the sharing activity was successful, I have this code:
UIActivityViewController *controller = [[UIActivityViewController alloc]
initWithActivityItems:#[text, shortURL, image]
applicationActivities:nil];
[controller setCompletionWithItemsHandler:^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {
if (! completed){
// Here I do some stuff irrelevant to the question
}
}];
Since I have copied (and modified) this code, I don't want to claim that I completely understand what is happening here.
What I do know, and this is my question, is that the code above runs fine on iOS 8 but not on iOS 7, hardware or simulator.
I dearly hope that somebody can explain to me what is going on here.
The completionWithItemsHandler property is not available in iOS 7, as it was introduced in iOS 8.
What you're looking for is the now-deprecated completionHandler property; if your deployment target is below iOS 8, you can just use this, but if you want to be future-proof, you can check whether the new handler is supported and, if not, use the old handler:
if([[UIApplication sharedApplication] respondsToSelector:(#selector(setCompletionWithItemsHandler:))]){
[controller setCompletionWithItemsHandler:^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {
if(!completed){
// Out of scope of question
}
}];
}else{
[controller setCompletionHandler:^(NSString *activityType, BOOL completed) {
if(!completed){
// Out of scope of question
}
}];
}
}
Also, you may have omitted this for brevity, but it's important that you actually present the view controller after initializing it:
[self presentViewController:controller animated:YES completion:nil];
OK, so this is what I did. Most likely, Kremelur answered it in general terms, but I am too much of a novice to understand that. So, I copied and pasted some stuff, after some cross-googling. I hope this is of any use to someone.
[controller setCompletionHandler:^(NSString *activityType, BOOL completed) {
NSLog(#"completed dialog - activity: %# - finished flag: %d", activityType, completed);
if (! completed){
// Out of scope of question
}
}];
This code seems to run fine in both iOS7 and iOS8.
Related
This question already has answers here:
iOS 9.3 freeze after calling openURL
(2 answers)
Closed 6 years ago.
I am using the share option in my app using UIActivityViewController; it's working fine in iOS 9.2 and Google+ share option is not working in iOS 9.3
To confirm this, I had downloaded other app which has the share option using UIActivityViewController, and the issue is the entire UI of the app is hanging up.
How can I resolve this issue?
Edit 1:
code:
NSURL * URL = [[NSURL alloc]initWithString:#"http://domainName/message.php?"];
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:URL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
[request setHTTPMethod:#"GET"];
NSString *tempEmailId = (NSString *)[[NSUserDefaults standardUserDefaults] objectForKey:CURRENT_USER_EMAIL_ID_UD_KEY];
NSString *tempPassword = (NSString *)[[NSUserDefaults standardUserDefaults] objectForKey:CURRENT_USER_PASSWORD_UD_KEY];
NSString *basicAuthCredentials = [NSString stringWithFormat:#"%#:%#", tempEmailId, tempPassword];
[request setValue:[NSString stringWithFormat:#"Basic %#", AFBase64EncodedStringFromString(basicAuthCredentials)] forHTTPHeaderField: #"Authorization"];
//NSLog(#"request %#\n",request);
[[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (data != nil) {
NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSArray * activityItems = #[responseString];
dispatch_async(dispatch_get_main_queue(), ^{
activityViewController = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:activities];
[activityViewController setValue:#"Today's Recommendations" forKey:#"subject"];
activityViewController.excludedActivityTypes = #[UIActivityTypePostToFacebook];
[activityViewController setCompletionWithItemsHandler:
^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"activityType: %#, returnedItems: %#, activityError: %#", activityType, returnedItems, activityError.userInfo);
if (completed)
{
NSLog(#"The Activity: %# was completed", activityType);
}
else
{
NSLog(#"The Activity: %# was NOT completed", activityType);
}
});
}];
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
[self presentViewController:activityViewController animated:YES completion:nil];
}
//if iPad
else {
activityViewController.modalPresentationStyle = UIModalPresentationPopover;
// activityViewController.popoverPresentationController.sourceView = sender;
activityViewController.popoverPresentationController.sourceView = self.view;
if ([sender isKindOfClass:[UIButton class]]) {
UIButton *btn = (UIButton *)sender;
activityViewController.popoverPresentationController.sourceRect = btn.frame;
}
[self presentViewController:activityViewController animated:YES completion:nil];
}
});
}
}] resume];
NOTE:: Mail, Twitter, and Evernote are working. Only Google+ is hanging up.
Edit 2:: I don't know exactly but I think- its not related to open URL. If it's related then please let me know HOW?
Some JavaScript problems occurred in iOS 9.3. Its clearly mentioned in below article. Its not a code problem, it's an Apple webview problem. Check attached quote and URL for your reference.
iOS 9.3 freezes when clicking a link in an email
One of the most common problems ... affects links in emails. When using iOS 9.3, some people have found that by clicking a link in the Mail email app, the iPhone or iPad will become unresponsive.
A temporary solution is to turn off JavaScript in the Safari app by going to Settings > Safari > Advanced then turn off the toggle next to JavaScript.
This solution isn't ideal, and thankfully Apple has pushed out a new update, iOS 9.3.1 which according to the release notes "fixes an issue that caused apps to be unresponsive after tapping on links in Safari and other apps."
To download and install the update open up Settings and select General then Software Update. You should now be able to turn JavaScript back on and can click on links in emails and other messages without iOS 9.3 freezing.
Reference Link: iOS 9.3 Problems
So I am doing just a basic facebook share inside my app, and it works fine on my devices (iPhone 6 OS 9.1 and iPad air 9.02) but doesn't work on my coworkers iPad Air 2 8.4.1 or iPhone 6 Plus 9.1. Anyone have any clue as to why this would be?
They are signed into facebook in the device settings. They also have the facebook app installed (I don't have the app, just signed in through settings)
Here's the screenshot of my device showing the message to share, the other devices just show the image and no text.
Here's the code I am using to share
- (void)shareTapped {
UIImage *image = self.pictureView.image;
NSString *postText = [NSString stringWithFormat:#"%#\n*%#\n%#\n%#, %# %#", self.event.shortDescription, self.event.eventCode, self.event.address, self.event.city, self.event.state, self.event.zip];
[[UtilitiesObject sharedInstance] shareMessage:postText image:image parentVC:self];
}
- (void)shareMessage:(NSString *)msg image:(UIImage *)image parentVC:(UIViewController *)parentVC {
NSArray *activityItems = #[msg];
if (image) {
activityItems = #[msg, image];
}
UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:nil];
// Tailor the list of services displayed
activityController.excludedActivityTypes = #[UIActivityTypeAssignToContact,
//UIActivityTypePostToFacebook,
//UIActivityTypePostToTwitter,
//UIActivityTypeMail,
UIActivityTypeMessage,
UIActivityTypeSaveToCameraRoll,
UIActivityTypePrint,
UIActivityTypePostToWeibo,
UIActivityTypeCopyToPasteboard];
activityController.popoverPresentationController.sourceView = parentVC.view;
[activityController setCompletionWithItemsHandler:
^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {
if ([activityType isEqualToString: UIActivityTypeMail]) {
NSLog(#"Mail");
}
if ([activityType isEqualToString:UIActivityTypePostToFacebook]) {
NSLog(#"Facebook");
}
if ([activityType isEqualToString:UIActivityTypePostToTwitter]) {
NSLog(#"Twitter");
}
}];
[parentVC presentViewController:activityController animated:YES completion:nil];
}
Facebook's platform policy does not allow apps to prefill the message field. In this case, because you don't have the Facebook app, it's using Apple's share sheet, which allows prefill but is against FB's platform policy. In your friends case, they're likely seeing the Facebook app's share extension, which correctly enforces the policy, and does not allow prefill.
Using Crittercism with some beta testers I am seeing an error appear several times that I've never experienced myself and I am unable to replicate.
Crittercism tells me:NSInternalInconsistencyException accessing _cachedSystemAnimationFence requires the main thread
And the line it is pointing to is:
[picker dismissViewControllerAnimated:YES completion:^{
Doing some reading on StackOverflow it appears that any UI code should be ran on the main thread. Is the error I am experiencing because the dismissViewControllerAnimated has been ran on a background thread?
Curious why this error is relatively random (i.e. I cannot reproduce it) and also how do I fix it.
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
__block PHObjectPlaceholder *assetPlaceholder;
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetChangeRequest *changeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:[info objectForKey:#"UIImagePickerControllerOriginalImage"]];
assetPlaceholder = changeRequest.placeholderForCreatedAsset;
} completionHandler:^(BOOL success, NSError *error) {
NSArray *photos = [[NSArray alloc] initWithObjects:assetPlaceholder.localIdentifier, nil];
PHFetchResult *savedPhotos = [PHAsset fetchAssetsWithLocalIdentifiers:photos options:nil];
[savedPhotos enumerateObjectsUsingBlock:^(PHAsset *asset, NSUInteger idx, BOOL *stop) {
NSMutableArray *images = self.event.eventAttachments;
if (images) {
[images addObject:asset];
} else {
images = [[NSMutableArray alloc]init];
[images addObject:asset];
}
self.event.eventAttachments = images;
[picker dismissViewControllerAnimated:YES completion:^{
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:4];
NSArray *indexPaths = [[NSArray alloc] initWithObjects:indexPath, nil];
[self.tblChildrenNotes beginUpdates];
[self.tblChildrenNotes reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
[self.tblChildrenNotes endUpdates];
}];
}];
}];
}
If we need to call any UI Related operation inside the block use dispatch.
Everything that interacts with the UI must be run on the main thread. You can run other tasks that don't relate to the UI outside the main thread to increase performance.
dispatch_async(dispatch_get_main_queue(), ^{
// Call UI related operations
});
I'm afraid I don't have a solution but I can offer the details of an app that is crashing the same way. We're using the Cordova platform to build our app. This crash only seems to happen in iOS9 (on an iPhone 6 in our case) and only when the user has Swype keyboard installed. We see the crash when opening/closing the keyboard to type in a text field displayed through Cordova's InAppBrowser plugin, and only sometimes. Deleting the Swype app makes the bug go away. Unfortunately, since we didn't write any of the objc involved in the app, we're having a tough time debugging. Good luck!
For Swift 3
DispatchQueue.main.async(execute: {
//UI Related Function
});
For me this solution fixed when trying to open pdfViewer when in landscape mode.
Check to make sure that your completionHandler is actually getting called back on the main thread and not some other thread. That is typically the cause for this particular issue.
The completion handler seems to work correctly for all the other share types (Twitter, Mail) but for Facebook, the complete BOOL is YES even when you cancel the share (having first tapped the Facebook icon).
UIActivityViewController *shareActivity = [[UIActivityViewController alloc] initWithActivityItems:#[title, url] applicationActivities:nil];
[shareActivity setCompletionWithItemsHandler:^(NSString *activityType, BOOL complete, NSArray *returnedItems, NSError *activityError) {
if (complete) { //Facebook share is always YES }];
Any suggestions?
iOS 8.3, Facebook App installed.
In my app I show more apps with SKStoreProductViewController, but the Apple store review team rejects it with the reason:
"An error message displays when tapping on the more apps button."
Everything works fine when I test it on my devices.
Below is the screenshot Apple sent me, what could be the problem?
Sample code:
__weak typeof(self) weakSelf = self;
SKStoreProductViewController* vc = [[SKStoreProductViewController alloc] init];
vc.delegate = self;
[vc loadProductWithParameters:#{SKStoreProductParameterITunesItemIdentifier : #1000000000} completionBlock:^(BOOL result, NSError * _Nullable error) {
if(result==NO){
//handle failure
return;
}
[weakSelf presentViewController:vc animated:YES completion:nil];
}];
ITMLKitErrorDomain errors frequently occur when a SKStoreProductViewController tries to call loadProductWithParameters with invalid parameters. Example full error:
<Warning>: [SKStoreProductViewController]: Did fail with error: Error Domain=ITMLKitErrorDomain Code=101 "The operation couldn’t be completed. (ITMLKitErrorDomain error 101.)" UserInfo={ ... } {ITMLKitErrorHTTPStatus=400}
Verify you do not have any typos or unexpected keys in your parameters dictionary when calling loadProductWithParameters. Verify the values for keys such as SKStoreProductParameterITunesItemIdentifier and SKStoreProductParameterAffiliateToken are valid.
If you are not experiencing this issue on test devices, just send it to review again, this could be a temporary issue with itunes site (it is used to show these "more apps", isn't it?). There are several mentions of that problem over the internet without any solution.
During investigation of youre issue it is possible to conclude that is quite rare case that could be connected with wrong product id in case of SkProductViewController. Also you should check if you are trying to show single app or amount of them. Because Apple have bug that is connected with showing of multiple items.
I am using SKStoreProductViewController in this way. This is code block that show app in App Store:
SKStoreProductViewController *storeProductViewController = [[SKStoreProductViewController alloc] init];
[storeProductViewController setDelegate:self];
[storeProductViewController loadProductWithParameters:#{SKStoreProductParameterITunesItemIdentifier : #"xxxxx"} completionBlock:^(BOOL result, NSError *error) {
if (error) {
NSLog(#"Error %# with User Info %#.", error, [error userInfo]);
} else {
[self presentViewController:storeProductViewController animated:YES completion:nil];
}
}];
Then i use delegate SKStoreProductViewControllerDelegate like this:
- (void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController {
[self dismissViewControllerAnimated:YES completion:nil];
}
Also i use [button setExclusiveTouch:YES]; because customers some times press few buttons with products. Also test you're id if it is single product.
I just finished dealing with this same issue. Everything works just fine when testing the app but the App Review team was rejecting my app for showing an alert view with the error returned by the call to loadProductWithParameters.
I worked around the issue by launching the App Store in Safari if the call to loadProductWithParameters fails. This provides a useful fallback in the rare cases when SKStoreProductViewController isn't working.
SKStoreProductViewController *vc = [[SKStoreProductViewController alloc] init];
vc.delegate = self;
NSDictionary *parameters = #{ SKStoreProductParameterITunesItemIdentifier : someAppId };
[vc loadProductWithParameters:parameters completionBlock:^(BOOL result, NSError *error) {
if (result) {
[someController presentViewController:vc animated:YES completion:nil];
} else {
NSURL *appURL = [NSURL URLWithString:[NSString stringWithFormat:#"https://itunes.apple.com/app/id%#?mt=8", someAppId]];
if ([[UIApplication sharedApplication] canOpenURL:appURL]) {
[[UIApplication sharedApplication] openURL:appURL];
} else {
// display the error in an alert
}
}
}];
I've had a rejection for the same reason (2 rejections) and I've found that I get this exact error testing without Wi-Fi (on a Wi-Fi only device).
So my thought is that Apple is testing this on a Wi-Fi device (they said they are testing on a Wi-Fi iPad) and they have disabled Wi-Fi. It would be nice if in the rejection they told you about the fact that they were testing with no internet access but you need to read between the lines.
So since you can't display the controller without an internet connection you need to show an appropriate error like "Please check your internet connection and try again."
Definitely don't show the localized description for the Error returned to the user.