Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIActivityViewController is not working in iOS 11

I am using UIActivityViewController to share a article url, using the below code,

UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:shareItemArray applicationActivities:nil];

activityVC.excludedActivityTypes = @[UIActivityTypePrint, UIActivityTypeCopyToPasteboard, UIActivityTypeAssignToContact, UIActivityTypeSaveToCameraRoll, UIActivityTypeAirDrop]; 

[self presentViewController:activityVC animated:YES completion:nil];

The above code working in iOS 9 & 10, but it is not working in iOS 11

I debugged it, the code is executing fine, after that i am getting a error log in console like below

[ShareSheet] ERROR: timed out waiting to establish a connection to the ShareUI view service extension.

Is there any people facing this problem? Is there a workaround?

EDIT: After clean and run the project, i tried to do the same, after 2 or 3 times the UIActivityViewController got opened, again i tried, for the first time i am getting the same above error, second time only the UIActivityViewController is getting opened.

like image 870
R. Mohan Avatar asked Sep 25 '17 07:09

R. Mohan


3 Answers

All code that modifies the user interface needs to be run in the main queue, that's by design. So all you need to do is this:

UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:shareItemArray applicationActivities:nil];

activityVC.excludedActivityTypes = @[UIActivityTypePrint, UIActivityTypeCopyToPasteboard, UIActivityTypeAssignToContact, UIActivityTypeSaveToCameraRoll, UIActivityTypeAirDrop]; 

dispatch_async(dispatch_get_main_queue(), ^{
    [self presentViewController:activityVC animated:YES completion:nil];
});

A little more explanation: dispatch_async() will enqueue the block you pass to it to run in a near future when it will be safe to update the UI. If you don't do that on the main queue, weird things can happen (sometimes the UI simply doesn't change, or old changes can be applied after newer ones, or stuff like that).

Methods that are messaged from user actions in the UI (for example, in IBAction when you tap a button) already run on the main queue, so dispatch_async() is not necessary there (of course, assuming you're not calling those IBActions manually from another queue).

Note that alloc/init and setExcludedActivityTypes: don't update the UI, so there's no need to call those on the main queue.

like image 114
Alejandro Iván Avatar answered Nov 09 '22 08:11

Alejandro Iván


For swift 4.0

let activityViewController: UIActivityViewController = UIActivityViewController(activityItems: [shareItem], applicationActivities:nil)
activityViewController.excludedActivityTypes = [.print, .copyToPasteboard, .assignToContact, .saveToCameraRoll, .airDrop]

DispatchQueue.main.async {
   self.present(activityViewController, animated: true, completion: nil);
}
like image 38
vp2698 Avatar answered Nov 09 '22 08:11

vp2698


Try this:

    dispatch_async(dispatch_get_main_queue(), ^{
         UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:shareItemArray applicationActivities:nil];

         activityVC.excludedActivityTypes = @[UIActivityTypePrint, UIActivityTypeCopyToPasteboard, UIActivityTypeAssignToContact, UIActivityTypeSaveToCameraRoll, UIActivityTypeAirDrop]; 
         dispatch_async(dispatch_get_main_queue(), ^{
               [self presentViewController:activityVC animated:YES completion:nil];
         });
    });

I had same problem, but in Swift3 and it works fine.

like image 28
Xande Rasta Moura Avatar answered Nov 09 '22 10:11

Xande Rasta Moura