38

This is the some peace of code for twitter... I want to know how to get the share action view like we get in iOS stock photos app...

@IBAction func twitterButton(sender: AnyObject) {
    
        let image: UIImage = UIImage(named: "LaunchScreenImage.png")!
        
        let twitterControl = SLComposeViewController(forServiceType: SLServiceTypeTwitter)
        twitterControl.setInitialText("")
        twitterControl.addImage(image)
        
        let completionHandler = {(result:SLComposeViewControllerResult) -> () in
            twitterControl.dismissViewControllerAnimated(true, completion: nil)
            switch(result){
            case SLComposeViewControllerResult.Cancelled:
                print("User canceled", terminator: "")
            case SLComposeViewControllerResult.Done:
                print("User tweeted", terminator: "")
            }
    }
        twitterControl.completionHandler = completionHandler
        self.presentViewController(twitterControl, animated: true, completion: nil)

}
Santosh
  • 997
  • 1
  • 7
  • 20
  • 1
    This question has a very good answer: http://stackoverflow.com/questions/35931946/basic-example-for-sharing-text-or-image-with-uiactivityviewcontroller-in-swift – Glenn Posadas Feb 22 '17 at 08:37

9 Answers9

57

Swift 5:

    // Setting description
    let firstActivityItem = "Description you want.."

    // Setting url
    let secondActivityItem : NSURL = NSURL(string: "http://your-url.com/")!
    
    // If you want to use an image
    let image : UIImage = UIImage(named: "your-image-name")!
    let activityViewController : UIActivityViewController = UIActivityViewController(
        activityItems: [firstActivityItem, secondActivityItem, image], applicationActivities: nil)
    
    // This lines is for the popover you need to show in iPad
    activityViewController.popoverPresentationController?.sourceView = (sender as! UIButton)
    
    // This line remove the arrow of the popover to show in iPad
    activityViewController.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection.down
    activityViewController.popoverPresentationController?.sourceRect = CGRect(x: 150, y: 150, width: 0, height: 0)
    
    // Pre-configuring activity items
    activityViewController.activityItemsConfiguration = [
    UIActivity.ActivityType.message
    ] as? UIActivityItemsConfigurationReading
    
    // Anything you want to exclude
    activityViewController.excludedActivityTypes = [
        UIActivity.ActivityType.postToWeibo,
        UIActivity.ActivityType.print,
        UIActivity.ActivityType.assignToContact,
        UIActivity.ActivityType.saveToCameraRoll,
        UIActivity.ActivityType.addToReadingList,
        UIActivity.ActivityType.postToFlickr,
        UIActivity.ActivityType.postToVimeo,
        UIActivity.ActivityType.postToTencentWeibo,
        UIActivity.ActivityType.postToFacebook
    ]
    
    activityViewController.isModalInPresentation = true
    self.present(activityViewController, animated: true, completion: nil)
Santosh
  • 997
  • 1
  • 7
  • 20
  • 3
    To get this to work today (in 2020) I had to change `= (sender as! UIButton)` to `= self.view` as I couldn't cast a UIButton or UIBarButton as a view. – podcastfan88 Jul 13 '20 at 12:46
  • 1
    @podcastfan88 you don't need to do that. `UIPopoverPresentationController` has a property called `barButtonItem` specifically for the purpose of anchoring to a navigation bar button. – Ash Feb 22 '21 at 08:37
  • wheres the completion handler? – Dave Apr 27 '21 at 18:55
29

This is how I implemented sharing with Swift 4/5 using a right button on the Navigation Controller. It includes an image, text and link.

SWIFT 4/5

On ViewDidLoad

 navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Share", style: .plain, target: self, action: #selector(share(sender:)))

Create the function

 @objc func share(sender:UIView){
        UIGraphicsBeginImageContext(view.frame.size)
        view.layer.render(in: UIGraphicsGetCurrentContext()!)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        let textToShare = "Check out my app"

        if let myWebsite = URL(string: "http://itunes.apple.com/app/idXXXXXXXXX") {//Enter link to your app here
            let objectsToShare = [textToShare, myWebsite, image ?? #imageLiteral(resourceName: "app-logo")] as [Any]
            let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)

            //Excluded Activities
            activityVC.excludedActivityTypes = [UIActivity.ActivityType.airDrop, UIActivity.ActivityType.addToReadingList]
            //

            activityVC.popoverPresentationController?.sourceView = sender
            self.present(activityVC, animated: true, completion: nil)
        }    }
JP Aquino
  • 2,958
  • 1
  • 17
  • 22
21
  @IBAction func shareButtonClicked(sender: AnyObject)
    {
        //Set the default sharing message.
        let message = "Message goes here."
        //Set the link to share.
        if let link = NSURL(string: "http://yoururl.com")
        {
            let objectsToShare = [message,link]
            let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
            activityVC.excludedActivityTypes = [UIActivityTypeAirDrop, UIActivityTypeAddToReadingList]
            self.presentViewController(activityVC, animated: true, completion: nil)
        }
    }

This will allow you to present a UIActivityViewController to share a link and a message with any application that will accept them.

onemillion
  • 612
  • 4
  • 18
  • It works when selecting whatsapp to share, but it cannot show the message when we select wechat/facebook to share. is anyone can solve this issue? – Eric Chong Oct 21 '17 at 03:23
15

Details

  • Xcode 11.4.1 (11E503a), Swift 5.2

Solution

TopViewController solution

extension UIApplication {
    class var topViewController: UIViewController? { return getTopViewController() }
    private class func getTopViewController(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
        if let nav = base as? UINavigationController { return getTopViewController(base: nav.visibleViewController) }
        if let tab = base as? UITabBarController {
            if let selected = tab.selectedViewController { return getTopViewController(base: selected) }
        }
        if let presented = base?.presentedViewController { return getTopViewController(base: presented) }
        return base
    }

    private class func _share(_ data: [Any],
                              applicationActivities: [UIActivity]?,
                              setupViewControllerCompletion: ((UIActivityViewController) -> Void)?) {
        let activityViewController = UIActivityViewController(activityItems: data, applicationActivities: nil)
        setupViewControllerCompletion?(activityViewController)
        UIApplication.topViewController?.present(activityViewController, animated: true, completion: nil)
    }

    class func share(_ data: Any...,
                     applicationActivities: [UIActivity]? = nil,
                     setupViewControllerCompletion: ((UIActivityViewController) -> Void)? = nil) {
        _share(data, applicationActivities: applicationActivities, setupViewControllerCompletion: setupViewControllerCompletion)
    }
    class func share(_ data: [Any],
                     applicationActivities: [UIActivity]? = nil,
                     setupViewControllerCompletion: ((UIActivityViewController) -> Void)? = nil) {
        _share(data, applicationActivities: applicationActivities, setupViewControllerCompletion: setupViewControllerCompletion)
    }
}

Usage

UIApplication.share("Text to share")

let data = ["Text, Image and url", image, url] as [Any]
UIApplication.share(data)

Full sample

Do not forget to add the solution code here (look above)

import UIKit

class ViewController: UIViewController {

    private weak var imageView: UIImageView?
    override func viewDidLoad() {
        super.viewDidLoad()

        var button = UIButton(frame: CGRect(x: 50, y: 50, width: 200, height: 40))
        button.setTitle("Share text", for: .normal)
        button.addTarget(self, action: #selector(shareButtonTapped), for: .touchUpInside)
        button.setTitleColor(.blue, for: .normal)
        view.addSubview(button)

        button = UIButton(frame: CGRect(x: 50, y: 80, width: 200, height: 40))
        button.setTitle("Share text & image", for: .normal)
        button.addTarget(self, action: #selector(shareCombinedData), for: .touchUpInside)
        button.setTitleColor(.blue, for: .normal)
        view.addSubview(button)

        let imageView = UIImageView(frame: CGRect(x: 50, y: 120, width: 200, height: 200))
        imageView.image = UIImage(named: "image")
        imageView.isUserInteractionEnabled = true
        imageView.contentMode = .scaleAspectFill
        imageView.clipsToBounds = true
        imageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(imageViewTapped)))
        view.addSubview(imageView)
        self.imageView = imageView

    }

    @objc func shareButtonTapped() { UIApplication.share("Text to share") }
    @objc func imageViewTapped() {
        guard let image = imageView?.image else { return }
        UIApplication.share(image)
    }
    @objc func shareCombinedData() {
        guard let image = imageView?.image, let url = URL(string: "http://google.com") else { return }
        let data = ["Text, Image and url", image, url] as [Any]
        UIApplication.share(data)
    }
}

Sample result

enter image description here enter image description here

Vasily Bodnarchuk
  • 19,860
  • 8
  • 111
  • 113
  • Nice, but it's probably better to build own protocol instead of overriding Equitable, and then conform your desired types to it. Your solution can be misleading a bit. – caffeinum Dec 03 '18 at 08:50
  • @caffeinum I am not overriding any function. I just add new functions. Why not, your idea I interesting too. – Vasily Bodnarchuk Dec 03 '18 at 15:12
  • Nice implementation, but how will you share multiple items e.g. text, image and URL at once? – Hackman May 20 '20 at 08:08
6

I develop @onemillion 's answer:) You can use this for Swift 3

override func viewDidLoad() {
    super.viewDidLoad()

    share(message: "selam", link: "htttp://google.com")
}

func share(message: String, link: String) {
    if let link = NSURL(string: link) {
        let objectsToShare = [message,link] as [Any]
        let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
        self.present(activityVC, animated: true, completion: nil)
    }
}
Celil Bozkurt
  • 1,484
  • 14
  • 14
  • These examples... On what planet is there a share button that shares a single link? how about an example that gets the current URL, which is kind of like 99% of all use cases here... sorry had to rant at someone – AlxVallejo Dec 16 '17 at 15:56
4

UPDATED FOR SWIFT 3.0

// first function to add the button to your navigation bar

func addingNavBarBtn () {

    // setting button's image

    let comunicateImage = UIImage(named: "NavfShare")

    let comunicateBtn = UIBarButtonItem(image: comunicateImage, style: .plain, target: self, action: #selector(shareButtonPressed))

    comunicateBtn.tintColor = UIColor.white

    self.navigationItem.rightBarButtonItem = comunicateBtn

}

//setting button's action

func shareButtonPressed(){

    //checking the object and the link you want to share


    let urlString = "https://www.google.com"



    let linkToShare = [urlString!]

    let activityController = UIActivityViewController(activityItems: linkToShare, applicationActivities: nil)

    self.present(activityController, animated: true, completion: nil)

}
MhmdRizk
  • 1,266
  • 11
  • 27
  • where did mainAboutUsObject come from? Sorry not familiar with swift, but how do you get the URL of the current page in Safari for example? – AlxVallejo Dec 16 '17 at 15:58
  • @AlxVallejo the mainAboutUsObject is just an object returned by an API call , you can replace it with any URL you have to open it in safari – MhmdRizk Dec 16 '17 at 16:53
  • What API call? There is no API call in your example. This var just comes out of the blue in the code. It happens automatically? Does that mean it would automatically refer to the link you are sharing? This is BASIC stuff that none of these examples seem to address. – AlxVallejo Dec 16 '17 at 18:21
  • @AlxVallejo no dear , you don't need to know anything about the API call , this variable caries the url string , this is what you need to know – MhmdRizk Dec 16 '17 at 18:24
4

Improving on JP Aquino's code for Swift 5 for share action rightBarButtonItem on the Navigation Controller.

In viewDidLoad of your ViewController, do this:

 navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .action, target: self, action: #selector(shareBarButtonItemClicked(_:)))

Then implement the shareBarButtonItemClicked method as below somewhere inside your ViewController:

  @objc func shareBarButtonItemClicked(_ sender: UIBarButtonItem) {
    // Text to share with other apps
    let textToShare = String(describing: "My awesome app")
    // URL, and or, and image to share with other apps
    guard let myAppURLToShare = URL(string: "http://itunes.apple.com/app/idXXXXXXXXX"), let image = UIImage(named: "image.jpg") else {
        return
    }
    let items = [textToShare, myAppURLToShare, image] as [Any]
    let avc = UIActivityViewController(activityItems: items, applicationActivities: nil)

    //Apps to exclude sharing to
    avc.excludedActivityTypes = [
        UIActivityType.airDrop,
        UIActivityType.print,
        UIActivityType.saveToCameraRoll,
        UIActivityType.addToReadingList
    ]
    //If user on iPad
    if UIDevice.current.userInterfaceIdiom == .pad {
        if avc.responds(to: #selector(getter: UIViewController.popoverPresentationController)) {
            avc.popoverPresentationController?.barButtonItem = sender
        }
    }
    //Present the shareView on iPhone
    self.present(avc, animated: true, completion: nil)
}

Happy coding!

Vick Swift
  • 2,399
  • 13
  • 17
3
let items = ["Your Sharing Content"];
let activity = UIActivityViewController(activityItems: items, applicationActivities: nil);
self.present(activity, animated: true, completion: nil)
jarora
  • 4,400
  • 2
  • 30
  • 39
Amul4608
  • 1,232
  • 12
  • 25
2
@IBAction func shareButtonAction(_ sender: UIButton) {   

let activityVC = UIActivityViewController(activityItems: ["Whatever you    want to share"], applicationActivities: nil)
    activityVC.popoverPresentationController?.sourceView = sender
    present(activityVC, animated: true, completion: nil)
    activityVC.completionWithItemsHandler = { (activityType, completed:Bool, returnedItems:[Any]?, error: Error?) in
        
        if completed  {
            self.dismiss(animated: true, completion: nil)
        }
    }
}
iOS Developer
  • 3,393
  • 2
  • 38
  • 56
Dian
  • 155
  • 3
  • 12