Using UIActivityViewController (Swift)
Last week at work I found myself into interesting problem. We had to show the share action sheet. Not just Facebook, Twitter or Google plus, but the one iOS natively offers like this,
At the first look it looked quite daunting. So as usual I inflated my estimate to 4 hours. Though I was not quite sure if that would be enough in spite of escalated time.
-
Creating custom
UIActivity
objects:
In the following paragraph we will create two custom application activities as follows -
Custom application activity object to show Google search
class CustomActivityOne: UIActivity {
override func activityType() -> String? {
return "jayesh.activityType.Search"
}
override func activityTitle() -> String? {
return "Search Engine"
}
override func activityImage() -> UIImage? {
return UIImage(named: "google")
}
override func canPerformWithActivityItems(activityItems: [AnyObject]) -> Bool {
return true
}
override func prepareWithActivityItems(activityItems: [AnyObject]) {
}
override func performActivity() {
UIApplication.sharedApplication().openURL(NSURL(string: "https://www.google.com")!)
}
}
- Custom application activity object to show custom view controller
class CustomActivityTwo: UIActivity {
var navController: UINavigationController = UINavigationController()
override func activityType() -> String? {
return "jayesh.activityType.Obama"
}
override func activityTitle() -> String? {
return "President"
}
override func activityImage() -> UIImage? {
return UIImage(named: "obama_icon")
}
override func canPerformWithActivityItems(activityItems: [AnyObject]) -> Bool {
return true
}
override func prepareWithActivityItems(activityItems: [AnyObject]) {
}
override func activityViewController() -> UIViewController? {
let presidentViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("president")
navController = UINavigationController(rootViewController: presidentViewController)
presidentViewController.title = "Barack Obama"
presidentViewController.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Cancel, target: self, action: #selector(dismissViewController))
return navController
}
func dismissViewController() {
navController.dismissViewControllerAnimated(true, completion: nil)
activityDidFinish(true)
}
}
So we have created two custom application activity objects. We will then add these custom objects to our
UIActivityViewController
during initialization.
We will first create a button. When user presses this button, we will present an activity view controller
As you can see in the above screenshot, two custom application activities I have added are visible in the activities list. Viz.
Google Search
andPresident
@IBAction func openActivityControllerButtonPressed(sender: UIButton) {
let activityItems = ["Please check out my website", NSURL(string: "https://www.jayeshkawli.ghost.io")!, "Awesome Donuts", UIImage(named: "donuts.jpg")!]
let searchActivity = CustomActivityOne()
let presidentActivity = CustomActivityTwo()
let customActivityTypes = [searchActivity, presidentActivity]
let activityIndicatorView = UIActivityViewController(activityItems: activityItems, applicationActivities: customActivityTypes)
activityIndicatorView.popoverPresentationController?.sourceView = sender
activityIndicatorView.completionWithItemsHandler = { (activityType, completed, returnedItems, error) in
if let activityName = activityType?.componentsSeparatedByString(".").last {
let completedString = completed ? "Completed" : "Cancelled"
let operationFinishMessage = "Activity '\(activityName)' \(completedString)"
self.showMessage(operationFinishMessage)
}
}
self.presentViewController(activityIndicatorView, animated: true, completion: nil)
}
Also, when user performs any action from activity items, based on the action taken, we will also show an alert dialogue whether action was completed or cancelled.
func showMessage(alertDetail: String) {
let alertController = UIAlertController(title: "Activity View Controller Demo", message: alertDetail, preferredStyle: .Alert)
let alertAction = UIAlertAction(title: "OK", style: .Default, handler: nil)
alertController.addAction(alertAction)
self.presentViewController(alertController, animated: true, completion: nil)
}
- Please note that in addition to application activities, I have also added another set of
activityItems
as follows :
-
Item to share an URL. User can add it to reading list of open with Safari
-
Item to share an image. User can store it in the photos or share it though a message
let activityItems = ["Please check out my website", NSURL(string: "https://www.jayeshkawli.ghost.io")!, "Awesome Donuts", UIImage(named: "donuts.jpg")!]
And then we initialize out UIActivityViewController
with these custom activities and present it on the viewport.
let activityIndicatorView = UIActivityViewController(activityItems: activityItems, applicationActivities: customActivityTypes)
self.presentViewController(activityIndicatorView, animated: true, completion: nil)
You can also get a callback when user selects activity items from list, action is successfully performed or cancelled as follows :
activityIndicatorView.completionWithItemsHandler = { (activityType, completed, returnedItems, error) in
if let activityName = activityType?.componentsSeparatedByString(".").last {
let completedString = completed ? "Completed" : "Cancelled"
let operationFinishMessage = "Activity '\(activityName)' \(completedString)"
self.showMessage(operationFinishMessage)
}
}
I have hosted the full code for this project on GitHub too. Feel free to give any suggestions or comments. Any pull requests or critics are most welcome.