iPad上的UIActivityViewController

17

我一直在使用以下代码来显示UIActivityViewController,在使用Xcode 6、Swift 1.2和iOS 8时运行良好。然而,当我更新后,它会显示UIActivityViewController,但是完全没有任何共享选项。你有什么建议吗?

if UIDevice.currentDevice().userInterfaceIdiom == .Pad {
        let textToShare = textViewOne.text

            let objectsToShare = [textToShare]
            let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)

            let nav = UINavigationController(rootViewController: activityVC)
            nav.modalPresentationStyle = UIModalPresentationStyle.Popover
            let popover = nav.popoverPresentationController as UIPopoverPresentationController!

            popover.sourceView = self.view
            popover.sourceRect = sender.frame

            self.presentViewController(nav, animated: true, completion: nil)

    } else {
        let textToShare = textViewOne.text

        let objectsToShare = [textToShare]
        let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)

        self.presentViewController(activityVC, animated: true, completion: nil)

    }

UIActivityViewController 支持 iOS 8 或以上版本,在 Xcode 7 编译时是否会显示任何警告信息。 - Manikandan D
你好。很遗憾没有警告信息。它可以在iPhone上运行,但在iPad上无法运行。 - Tom Coomer
我认为你不需要在弹出窗口中显示活动控制器,如果你像 iPhone 一样处理它会发生什么? - Björn Ro
1
当我只使用 iPhone 部分时,它会崩溃并出现以下提示:UIPopoverPresentationController (<_UIAlertControllerActionSheetRegularPresentationController: 0x135db4490>) should have a non-nil sourceView or barButtonItem set before the presentation occurs. - Tom Coomer
7个回答

21

这解决了它。

let objectsToShare = [textToShare]
let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
activityVC.title = "Share One"
activityVC.excludedActivityTypes = []            
activityVC.popoverPresentationController?.sourceView = self.view
activityVC.popoverPresentationController?.sourceRect = sender.frame
self.presentViewController(activityVC, animated: true, completion: nil)

在Swift 3.0中:

let objectsToShare = [textToShare]
let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
activityVC.title = "Share One"
activityVC.excludedActivityTypes = []
        
activityVC.popoverPresentationController?.sourceView = self.view
activityVC.popoverPresentationController?.sourceRect = sender.frame

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

20

由于sender在某些情况下不在范围内,我在尝试使用SWIFT 5中的上述建议时遇到了困难。

activity.popoverPresentationController?.sourceRect = sender.frame

尝试改用CGRect设置,例如:

activityController.popoverPresentationController?.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY,width: 0,height: 0)

我希望这能帮助一些人。


2
这在一些iPad型号上是必要的,至少如此。 - Andrew Koster

13

Swift 4.0

    let shareText = "Hi"
    let activity = UIActivityViewController(activityItems: shareText, applicationActivities: nil)
    activity.excludedActivityTypes = []

    if UIDevice.current.userInterfaceIdiom == .pad {
        activity.popoverPresentationController?.sourceView = self.view
        activity.popoverPresentationController?.sourceRect = sender.frame
    }
    self.present(activity, animated: true, completion: nil)

2
我遇到了一个不同的问题。我希望 UIActivityViewController 在屏幕中央停留,但在 iPad 旋转至横屏时它会偏离中心。
横屏错误示例:

enter image description here

有两种解决方法:将 UIActivityViewController 设为类属性,并且非常重要的是在 viewDidLayoutSubviews 中设置其 sourceRect。按照以下5个步骤操作:
// 1. make the activityVC a class property
var activityVC: UIActivityViewController?

override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

    if UIDevice.current.userInterfaceIdiom == .pad {
        // 2. set its sourceRect here. It's the same as in step 4           
        activityVC?.popoverPresentationController?.sourceRect = CGRect(x: UIScreen.main.bounds.width / 2, y: UIScreen.main.bounds.height / 2, width: 0, height: 0)
    }
}

// 3. present the UIActivityViewController
func presentActivityVC() {

    let objectsToShare = [textToShare]

    activityVC = nil
    activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
    activityVC?.excludedActivityTypes = [.addToReadingList, .openInIBooks, .print]
    activityVC?.popoverPresentationController?.sourceView = self.view

    if UIDevice.current.userInterfaceIdiom == .phone {
        activityVC?.modalPresentationStyle = .overFullScreen
    }
        
    if UIDevice.current.userInterfaceIdiom == .pad {
        // 4. set its sourceRect here. It's the same as in step 2
        activityVC?.popoverPresentationController?.sourceRect = CGRect(x: UIScreen.main.bounds.width / 2, y: UIScreen.main.bounds.height / 2, width: 0, height: 0)
        activityVC?.popoverPresentationController?.permittedArrowDirections = []
    }

    present(activityVC!, animated: true, completion: nil)

    activityVC?.completionWithItemsHandler = { [weak self](activityType, completed:Bool, returnedItems:[Any]?, error: Error?) in
        if let error = error {
            print(error.localizedDescription)
            return
        }

        // 5. set the activityVC to nil after the user is done 
        DispatchQueue.main.async { [weak self] in
            self?.activityVC = nil
        }
    }
}

现在旋转时,无论是横屏还是竖屏,图像都会居中。
横屏正确示例: enter image description here 竖屏正确示例: enter image description here

很好,解决了我的问题。 - Metin Atalay
1
@MetinAtalay 很高兴能帮到你!如果解决了你的问题,请点赞支持一下。 - Lance Samaria

0
如果你想将弹出窗口附加到发送者视图的界限上,那么以下代码将起作用:
let vc = UIActivityViewController(activityItems: [url], applicationActivities: nil)
if UIDevice.current.userInterfaceIdiom == .pad {
  vc.popoverPresentationController?.sourceView = sender
  vc.popoverPresentationController?.sourceRect = CGRect(origin: CGPoint.zero, size: sender.frame.size)
}

sourceRect 是在 sourceView 的坐标系中定义的,因此我们需要将 sourceRect 的原点指定为 CGPoint.zero 而不是 sender.frame.origin


0

我们需要为iPad特别设置sourceView和sourceRect。

我们可以尝试下面的代码片段:

activityViewController.popoverPresentationController?.sourceView = sender.self
activityViewController.popoverPresentationController?.sourceRect = CGRect(x: self.view.bounds.minX + sender.frame.width/2, y: self.view.bounds.minY, width: 0, height: 0)
activityViewController.popoverPresentationController?.permittedArrowDirections = []

它会将sourceView设置为发送者的,并将sourceRect设置为UI的中心。

我们将sender.frame.width/2添加到x坐标上,并且还移除了锚点箭头,以确保弹出窗口正好位于中心位置。


0

已更新至 Swift 4 ~ 5,并提供了操作事件示例,还会显示箭头。
在 iPadOS 15.7.2 & iOS 16.1、13.6 上进行了测试。

@objc
private final func handleShareButtonPress(_ sender: UIButton) {
    
    let urlString = Manager.getShareEventBaseURL
    guard let url = URL(string: urlString) else { return }
    let items: [Any] = [url]
    let activityController = UIActivityViewController(activityItems: items, applicationActivities: nil)
    activityController.title = "\(user.name) sharing with you."
    if let popoverController = activityController.popoverPresentationController {
        popoverController.sourceView = self.view // to set the source of your alert
        popoverController.sourceRect = sender.convert(sender.frame, to: self.view) /// Get correct rect of sender view
        popoverController.permittedArrowDirections = [.up] // declare the direction of sender to show arrow
    }

    present(activityController, animated: true)
}

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