Fresh Beginning
  • Home
  • Speaking
  • Reading
  • Github
  • Alma Mater
  • Contact
Subscribe
Swift

Using UIActivityViewController (Swift)

  • Jayesh Kawli

Jayesh Kawli

May 28, 2016 • 3 min read

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,

activity_view_controller

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

activity_view_controller_button

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 and President


@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 :
  1. Item to share an URL. User can add it to reading list of open with Safari

  2. 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.

Sign up for more like this.

Enter your email
Subscribe

Pull to Refresh Control and One Time Data Fetch Task in SwiftUI

iOS 15 introduced two new APIs to simplify data load and refresh actions. These APIs will allow users to trigger the data refresh on request and allow one-time data load execution on the very first run - For example, when the view has been loaded in the memory for the

  • Jayesh Kawli
Jayesh Kawli Jun 30, 2022 • 5 min read
SwiftUI - Using AsyncImage API in iOS15

SwiftUI - Using AsyncImage API in iOS15

Apple introduced an AsyncImage API in iOS15. This API solves the long-standing image download problem for iOS developers without using any third-party image downloading libraries. Asynchronously downloading remote images from URL has been a long pain point and having to add third-party frameworks only adds to this pain. Let's see

  • Jayesh Kawli
Jayesh Kawli Jun 28, 2022 • 5 min read
Low Data Mode on iOS 13

Low Data Mode on iOS 13

Apple introduced a low data mode feature in iOS 13. Using this mode, (On iOS 13), users can specify their preference to minimize the data usage when the network is really bad or they want to save on their data while being on the cellular. When the low data mode

  • Jayesh Kawli
Jayesh Kawli Jun 13, 2022 • 6 min read
Fresh Beginning © 2022
Powered by Ghost