Поделиться изображением с хэштегом через UIActivityViewController (Twitter, Facebook, Instagram)

Я пытаюсь поделиться изображением с хэштегом с помощью UIActivityViewController, и я сталкиваюсь со странным поведением при попытке поделиться в Twitter, Facebook и Instagram. Похоже, не так много документации о расширениях общего доступа к этим сервисам.

Сценарий 1: контроллер Init с массивом элементов действий с изображением и текстом

Если я инициализирую контроллер следующим образом, в контроллере появятся Twitter и Facebook (без Instagram, так как он не поддерживает текстовые элементы), и оба будут программно предварительно заполнять хэштег в поле ввода текста:

let activityVC = UIActivityViewController(activityItems: [myHashtagString, myImage], applicationActivities: nil)

Сценарий 2: контроллер Init только с изображением

В этом сценарии отображаются все сети, но я (очевидно) теряю функцию автоматического хэштега:

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

Сценарий 3: подкласс UIActivityItemSource

Если я сделаю свой собственный подкласс UIActivityItemSource, я почти все смогу заставить работать. Однако, и это то, что я не могу понять, используя методы протокола, как у меня ниже, приводит к тому, что автоматический хэштег работает для Facebook, но не для Twitter. Как это может быть возможно - нужен ли специальный ключ для Twitter? Должен быть способ, чтобы он работал, если он работает в Сценарии № 1...

Интересно, что этот метод работает как для Twitter, так и для Facebook, если я вставлю URL (закомментировано). Так с какой стати текст не будет работать для Твиттера!?

let activityItem = CustomItemSource(image: image, message: "#TestTag")
let activityVC = UIActivityViewController(activityItems: [activityItem], applicationActivities: nil)

...

class CustomItemSource: NSObject, UIActivityItemSource {

    private var image: UIImage!
    private var message: String!

    // MARK: Init
    init(image: UIImage, message: String) {
        super.init()

        self.image = image
        self.message = message
    }

    // MARK: Item Source Protocol
    func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
        return image
    }

    func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivityType) -> Any? {
        if activityType == .postToTwitter || activityType == .postToFacebook {
            //return ["url": URL(string: "https://www.google.com")!, "image": image]

            return ["text": message, "image": image]
        }
        else {
            return ["image": image]
        }
    }

}

1 ответ

Решение

Определить два UIActivityItemSource классы, один для изображения и один для текста.

В первом только вернуть изображение. Во втором возвращение NSObject() для placeHolder и вернуть Text или же nil в зависимости от активности. Возвращая NSObject(), UIActivity позволит всем услугам быть доступными.

UIActivityViewController(activityItems: [ImageProvider(), TextProvider()], applicationActivities: nil)

и провайдеры:

class TextProvider: NSObject, UIActivityItemSource {
    func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
        return NSObject()
    }

    func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivityType) -> Any? {
        if activityType == .postToTwitter || activityType == .postToFacebook {
            return "Tweet with #Hashtag"
        }
        return nil
    }
}

class ImageProvider: NSObject, UIActivityItemSource {
    func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
        return UIImage(named: ...)
    }

    func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivityType) -> Any? {
        return UIImage(named: ...)
    }
}

Explaination

Прежде всего, ключи не очень чувствительны. Единственным чувствительным ключом был "субъект" для электронной почты и приложений, поддерживающих его, который реализован в UIActivityControllerAPI, и мы можем установить его напрямую. Неважно, если вы предоставите UIImage с ключом "изображение" или "1".

Оказывается, активность в Твиттере не будет работать, если ее текст не будет возвращен напрямую в ...itemForActivity... метод. Таким образом, решение состоит в том, чтобы отделить источники предметов.

Активность в Твиттере также не будет работать, если placeholder получает что-то кроме String, но вернувшись String Активность в Instagram не сработает, поэтому вернувшись NSObject() Тип будет игнорироваться, и все услуги будут доступны. если вы хотите ограничить использование некоторых услуг UIActivityViewController.excludedActivityTypes

Другие вопросы по тегам