Podstawowy przykład udostępniania tekstu lub obrazu za pomocą UIActivityViewController w języku Swift

134

Rozpocząłem wyszukiwanie, chcąc wiedzieć, jak mogę udostępniać pliki innym aplikacjom na iOS. Odkryłem, że istnieją dwa ważne sposoby

  • UIActivityViewController
  • UIDocumentInteractionController

Te i inne metody są porównywane w tej odpowiedzi SO .

Często, kiedy uczę się nowej koncepcji, lubię zobaczyć podstawowy przykład, który pomoże mi zacząć. Gdy dostanę coś podstawowego, mogę później zmodyfikować to, jak mi się podoba.

Jest wiele pytań SO związanych z UIActivityViewController, ale nie mogłem znaleźć żadnego, które dotyczyło tylko prostego przykładu. Ponieważ właśnie się nauczyłem, jak to zrobić, poniżej podam własną odpowiedź. Możesz dodać lepszą (lub wersję Objective-C).

Suragch
źródło

Odpowiedzi:

282

Przykładowy projekt UIActivityViewController

Skonfiguruj scenorys za pomocą dwóch przycisków i podłącz je do kontrolera widoku (patrz kod poniżej).

wprowadź opis obrazu tutaj

Dodaj obraz do swojego Assets.xcassets. Nazwałem swojego „lwa”.

wprowadź opis obrazu tutaj

Kod

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 = [ UIActivityType.airDrop, UIActivityType.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 = [ UIActivityType.airDrop, UIActivityType.postToFacebook ]

        // present the view controller
        self.present(activityViewController, animated: true, completion: nil)
    }

}

Wynik

Kliknięcie „Udostępnij jakiś tekst” daje wynik po lewej stronie, a kliknięcie „Udostępnij obraz” daje wynik po prawej.

wprowadź opis obrazu tutaj

Uwagi

  • Przetestowałem to ponownie z iOS 11 i Swift 4. Musiałem uruchomić go kilka razy w symulatorze, zanim zadziałało, ponieważ upłynął limit czasu. Może to być spowodowane powolnym komputerem.
  • Jeśli chcesz ukryć niektóre z tych wyborów, możesz to zrobić, excludedActivityTypesjak pokazano w powyższym kodzie.
  • Nieuwzględnienie popoverPresentationController?.sourceViewlinii spowoduje awarię aplikacji po uruchomieniu na iPadzie.
  • Nie pozwala to na udostępnianie tekstu ani obrazów innym aplikacjom. Prawdopodobnie tego chcesz UIDocumentInteractionController.

Zobacz też

Suragch
źródło
1
Dlaczego niektóre przykłady pokazują tablicę 1 elementu, a niektóre pokazują 2? Zakładając udostępnianie obrazu.
Lim Thye Chean
@ Suragch: Cześć, chcę udostępnić kod polecający w tekście i chcę, aby ten kod został skopiowany po kliknięciu lub dotknięciu, jak to się dzieje, gdy wysyłamy numer.
Ishika
84

Udostępnij: tekst

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

Udostępnij: Obraz

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

Udostępnij: tekst - obraz - adres 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)
   }

wprowadź opis obrazu tutaj

Panie Javed Multani
źródło
4
hej, to nie działa. Na FB tylko link to udostępnij, a nie obraz i tekst.
Ekta Padaliya
@ScriptKitty. Czy aplikacja wiadomości jest poprawnie skonfigurowana z kontem I Cloud?
Awais Fayyaz,
1
@EktaPadaliya. Zgodnie z polityką aktualizacji FB można udostępniać adres URL lub obraz. tekst nie może
Awais Fayyaz
2
@ Obraz Mr.JavedMultani nie jest udostępniany w
WhatsApp
11

Jako uwaga, możesz również użyć tego dla iPadów:

activityViewController.popoverPresentationController?.sourceView = sender

Więc popover wyskakuje z nadawcy (w tym przypadku przycisk).

Adrien Brecheteau
źródło
activityViewController.popoverPresentationController? .sourceView = sender as? UIView -pracował dla mnie. :) dzięki
Brian
Pole udostępniania nie pojawiało się na iPadach. To rozwiązało problemy z iPadem, które miałem!
Asp Upload
11

Okazało się, że działa to bezbłędnie, jeśli chcesz udostępnić cały ekran.

@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)
}
Diavel Rider
źródło
4

Użyłem powyższej implementacji i właśnie teraz dowiedziałem się, że nie działa na iPadzie z systemem iOS 13. Musiałem dodać te linie przed wywołaniem funkcji present (), aby działała

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

Tak to działa u mnie

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)
    }
Bréndal Teixeira
źródło
3

Możesz użyć następujących funkcji, które napisałem w jednej z moich klas pomocniczych w projekcie.

Zadzwoń

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

i będzie działać zarówno na iPhonie, jak i na iPadzie. Jeśli przekażesz wartość CGRect dowolnego widoku przez sourceRect, wyświetli się również mała strzałka na iPadzie.

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)
}
Mahmud Ahsan
źródło
Działa doskonale! 👍🏻
Ravindra_Bhati
Zamiast szeregu ifzdań możesz pisać [url, image, msg].compactMap({ $0 }).
Avi