繁体   English   中英

在 Swift 中与 UIActivityViewController 共享文本或图像的基本示例

[英]Basic example for sharing text or image with UIActivityViewController in Swift

我开始搜索是想知道如何分享到 iOS 中的其他应用程序。我发现有两个重要的方法是

  • UIActivityViewController
  • UIDocumentInteractionController

此 SO answer中比较了这些方法和其他方法。

通常当我学习一个新概念时,我喜欢看一个基本的例子来帮助我入门。 一旦我完成了一些基本设置,我就可以稍后根据自己的喜好对其进行修改。

有很多与UIActivityViewController相关的问题,但我找不到任何只是要求一个简单示例的问题。 由于我刚刚学会了如何执行此操作,因此我将在下面提供自己的答案。 随意添加一个更好的(或 Objective-C 版本)。

UIActivityViewController 示例项目

用两个按钮设置你的故事板,并将它们连接到你的视图控制器(见下面的代码)。

在此处输入图片说明

将图像添加到您的 Assets.xcassets。 我叫我的“狮子”。

在此处输入图片说明

代码

import UIKit
class ViewController: UIViewController {
    
    // share text
    @IBAction func shareTextButton(_ sender: UIButton) {
        
        // text to share
        let text = "This is some text that I want to share."
        
        // set up activity view controller
        let textToShare = [ text ]
        let activityViewController = UIActivityViewController(activityItems: textToShare, applicationActivities: nil)
        activityViewController.popoverPresentationController?.sourceView = self.view // so that iPads won't crash
        
        // exclude some activity types from the list (optional)
        activityViewController.excludedActivityTypes = [ UIActivity.ActivityType.airDrop, UIActivity.ActivityType.postToFacebook ]
        
        // present the view controller
        self.present(activityViewController, animated: true, completion: nil)
        
    }
    
    // share image
    @IBAction func shareImageButton(_ sender: UIButton) {
        
        // image to share
        let image = UIImage(named: "Image")
        
        // set up activity view controller
        let imageToShare = [ image! ]
        let activityViewController = UIActivityViewController(activityItems: imageToShare, applicationActivities: nil)
        activityViewController.popoverPresentationController?.sourceView = self.view // so that iPads won't crash
        
        // exclude some activity types from the list (optional)
        activityViewController.excludedActivityTypes = [ UIActivity.ActivityType.airDrop, UIActivity.ActivityType.postToFacebook ]
        
        // present the view controller
        self.present(activityViewController, animated: true, completion: nil)
    }
    
}

结果

单击“共享一些文本”会在左侧给出结果,单击“共享图像”会在右侧给出结果。

在此处输入图片说明

笔记

  • 我用 iOS 11 和 Swift 4 重新测试了它。我不得不在模拟器中运行它几次,然后它才能工作,因为它超时了。 这可能是因为我的电脑很慢。
  • 如果你想隐藏一些选择,你可以做到这一点与excludedActivityTypes如上面的代码。
  • 不包括popoverPresentationController?.sourceView行将导致您的应用程序在 iPad 上运行时崩溃。
  • 这不允许您与其他应用程序共享文本或图像。 你可能想要UIDocumentInteractionController

也可以看看

分享 :文字

@IBAction func shareOnlyText(_ sender: UIButton) {
    let text = "This is the text....."
    let textShare = [ text ]
    let activityViewController = UIActivityViewController(activityItems: textShare , applicationActivities: nil)
    activityViewController.popoverPresentationController?.sourceView = self.view 
    self.present(activityViewController, animated: true, completion: nil)
}
}

分享 :图片

@IBAction func shareOnlyImage(_ sender: UIButton) {
    let image = UIImage(named: "Product")
    let imageShare = [ image! ]
    let activityViewController = UIActivityViewController(activityItems: imageShare , applicationActivities: nil)
    activityViewController.popoverPresentationController?.sourceView = self.view 
    self.present(activityViewController, animated: true, completion: nil)
 }

分享:文字 - 图片 - URL

   @IBAction func shareAll(_ sender: UIButton) {
    let text = "This is the text...."
    let image = UIImage(named: "Product")
    let myWebsite = NSURL(string:"https://stackoverflow.com/users/4600136/mr-javed-multani?tab=profile")
    let shareAll= [text , image! , myWebsite]
    let activityViewController = UIActivityViewController(activityItems: shareAll, applicationActivities: nil)
    activityViewController.popoverPresentationController?.sourceView = self.view 
    self.present(activityViewController, animated: true, completion: nil)
   }

在此处输入图片说明

请注意,您也可以将其用于 iPad:

activityViewController.popoverPresentationController?.sourceView = sender

所以弹出框从发件人(在那种情况下是按钮)弹出。

如果您想共享整个屏幕,我发现它可以完美运行。

@IBAction func shareButton(_ sender: Any) {

    let bounds = UIScreen.main.bounds
    UIGraphicsBeginImageContextWithOptions(bounds.size, true, 0.0)
    self.view.drawHierarchy(in: bounds, afterScreenUpdates: false)
    let img = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    let activityViewController = UIActivityViewController(activityItems: [img!], applicationActivities: nil)
    activityViewController.popoverPresentationController?.sourceView = self.view
    self.present(activityViewController, animated: true, completion: nil)
}

我已经使用了上面的实现,现在我才知道它在运行 iOS 13 的 iPad 上不起作用。我必须在 present() 调用之前添加这些行才能使其工作

//avoiding to crash on iPad
if let popoverController = activityViewController.popoverPresentationController {
     popoverController.sourceRect = CGRect(x: UIScreen.main.bounds.width / 2, y: UIScreen.main.bounds.height / 2, width: 0, height: 0)
     popoverController.sourceView = self.view
     popoverController.permittedArrowDirections = UIPopoverArrowDirection(rawValue: 0)
}

这就是它对我的作用

func shareData(_ dataToShare: [Any]){

        let activityViewController = UIActivityViewController(activityItems: dataToShare, applicationActivities: nil)

        //exclude some activity types from the list (optional)
        //activityViewController.excludedActivityTypes = [
            //UIActivity.ActivityType.postToFacebook
        //]

        //avoiding to crash on iPad
        if let popoverController = activityViewController.popoverPresentationController {
            popoverController.sourceRect = CGRect(x: UIScreen.main.bounds.width / 2, y: UIScreen.main.bounds.height / 2, width: 0, height: 0)
            popoverController.sourceView = self.view
            popoverController.permittedArrowDirections = UIPopoverArrowDirection(rawValue: 0)
        }

        self.present(activityViewController, animated: true, completion: nil)
    }

您可以使用我在项目中的一个助手类中编写的以下函数。

打电话

showShareActivity(msg:"message", image: nil, url: nil, sourceRect: nil) 

它适用于 iPhone 和 iPad。 如果你通过 sourceRect 传递任何视图的 CGRect 值,它也会在 iPad 中显示一个小箭头。

func topViewController()-> UIViewController{
    var topViewController:UIViewController = UIApplication.shared.keyWindow!.rootViewController!

    while ((topViewController.presentedViewController) != nil) {
        topViewController = topViewController.presentedViewController!;
    }

    return topViewController
}

func showShareActivity(msg:String?, image:UIImage?, url:String?, sourceRect:CGRect?){
    var objectsToShare = [AnyObject]()

    if let url = url {
        objectsToShare = [url as AnyObject]
    }

    if let image = image {
        objectsToShare = [image as AnyObject]
    }

    if let msg = msg {
        objectsToShare = [msg as AnyObject]
    }

    let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
    activityVC.modalPresentationStyle = .popover
    activityVC.popoverPresentationController?.sourceView = topViewController().view
    if let sourceRect = sourceRect {
        activityVC.popoverPresentationController?.sourceRect = sourceRect
    }

    topViewController().present(activityVC, animated: true, completion: nil)
}

iOS 分享文字或图片

现在的UIActivityViewController

let controller = UIActivityViewController(activityItems: [someObject], applicationActivities: nil) //someObject can be UIImage, NSURL, String... iOS decide how to handle it properly
controller.popoverPresentationController?.sourceView = self.view

controller.completionWithItemsHandler = {
    (
        activityType: UIActivity.ActivityType?,
        completed: Bool,
        arrayReturnedItems: [Any]?,
        error: Error?
    ) in
    
    if let error = error {
        //error occured
        return
    }
    
    if completed {
        if let activityType = activityType {
            switch activityType {
            case .saveToCameraRoll:
                break
            case .copyToPasteboard:
                break
            case .addToReadingList:
                break
            case .airDrop:
                break
            default:
                //all others
                break
            }
        }
    } else {
        //Cancel
    }
}

self.present(controller, animated: true)

如果要将图像保存到库中,请将NSPhotoLibraryAddUsageDescription添加到应用程序的.plist文件中,否则会出现运行时错误

This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSPhotoLibraryAddUsageDescription key with a string value explaining to the user how the app uses this data.

或者只是排除这个机会:

controller.excludedActivityTypes = [.saveToCameraRoll]

带有completionWithItemsHandler的变体,可以帮助添加后期逻辑或处理错误。

例如,将 UIImage 保存到相应处理程序中的照片库时,我遇到了下一个错误:

Error Domain=ALAssetsLibraryErrorDomain Code=-1 "Unknown error" UserInfo={NSLocalizedDescription=Unknown error, NSUnderlyingError=0x600003f85110 {Error Domain=PHPhotosErrorDomain Code=3303 "(null)"}}

正如我想通的那样,我试图保存CIImage 作为变体,您可以将其转换为CGImage

let context = CIContext()
guard let cgImage = context.createCGImage(output, from: output.extent) else { return nil }
return UIImage(cgImage: cgImage)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM