如何在Swift中实现“分享按钮”

51

这是一些用于 Twitter 的代码…… 我想知道如何获取类似于 iOS 股票照片应用程序中获得的共享操作视图...

@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)

}

1
这个问题有一个非常好的答案:https://dev59.com/OlsV5IYBdhLWcg3wrAdJ - Glenn Posadas
10个回答

72

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)

3
为了在2020年让这个工作起来,我不得不将= (sender as! UIButton)更改为= self.view,因为我无法将UIButton或UIBarButton转换为视图。 - podcastfan88
1
@podcastfan88,您不需要那么做。 UIPopoverPresentationController 有一个名为 barButtonItem 的属性,专门用于将其锚定到导航栏按钮上。 - Ash
完成处理程序在哪里? - Dave
目前我看来,只有在邮件应用程序中才能正确地分享文本、URL和图片。例如,在使用即时通讯应用程序进行共享时,只会考虑URL。 - laka

31

这是我使用导航控制器右侧按钮实现分享的Swift 4/5代码,包括图像、文本和链接。

SWIFT 4/5

在ViewDidLoad中:

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

创建函数

 @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)
        }    }

27
  @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)
        }
    }

这将允许您呈现一个UIActivityViewController,与任何能接受链接和消息的应用程序共享。


当选择WhatsApp分享时它可以正常工作,但是当我们选择微信/脸书分享时它无法显示消息。有没有人能够解决这个问题? - Eric Chong

16

详情

  • Xcode 11.4.1 (11E503a),Swift 5.2

解决方案

TopViewController 解决方案

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)
    }
}

使用方法

UIApplication.share("Text to share")

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

完整示例

别忘了在此处添加解决方案代码(请参考上面)

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)
    }
}

示例结果

输入图像描述 输入图像描述


不错,但建议自己构建协议而不是覆盖Equitable,并使您的所需类型符合该协议。否则您的解决方案可能有误导性。 - caffeinum
@caffeinum 我没有覆盖任何函数。我只是添加了新的函数。为什么不呢,你的想法也很有趣。 - Vasily Bodnarchuk
不错的实现,但是你如何一次分享多个项目,例如文本、图片和URL? - Hackman

8

我补充一下@onemillion的回答:)你可以在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)
    }
}

这些例子...在哪个星球上有一个分享单个链接的共享按钮?还有一个获取当前URL的示例,这有点像99%的所有用例...抱歉必须向某人发牢骚。 - AlxVallejo

5

已更新至Swift 3.0

// 添加按钮到导航栏的第一个函数

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)

}

mainAboutUsObject来自哪里?抱歉不熟悉Swift,但是例如如何在Safari中获取当前页面的URL? - AlxVallejo
@AlxVallejo,mainAboutUsObject只是一个API调用返回的对象,你可以用任何URL替换它,在Safari中打开。 - MhmdRizk
什么API调用?在你的例子中没有API调用。这个变量突然出现在代码中,它是自动发生的吗?这是否意味着它会自动引用你分享的链接?这是基础知识,但似乎这些例子都没有涉及到。 - AlxVallejo
@AlxVallejo 不用担心,你不需要了解API调用的任何内容,这个变量包含URL字符串,这就是你需要知道的。 - MhmdRizk

4
let items = ["Your Sharing Content"];
let activity = UIActivityViewController(activityItems: items, applicationActivities: nil);
self.present(activity, animated: true, completion: nil)

4

Swift 5 中,改进了 JP Aquino 的代码,用于在导航控制器上分享操作的 rightBarButtonItem。

在您的 ViewController 的 viewDidLoad 中,执行以下操作:

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

然后在您的ViewController内的某个地方按照下面的方式实现shareBarButtonItemClicked方法:

  @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)
}

愉快编码!


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)
        }
    }
}

0

IOS 16

从 IOS 16 开始,现在有一个共享链接按钮,只需将您的链接作为链接传递即可。

@available(iOS 16.0, *)
ShareLink(item: link) {
    Label("Click To Share", systemImage: "swift")
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接