【UIActivity】Twitter共有時にのみハッシュタグをつけたい!Instagramにも投稿したい!を実装してみた【Swift 3】
追記があります。
まだSwift3を使っています。Reoです。
UIActivityViewControllerを用いてシェアをするときに、
・Twitter共有では、ハッシュタグをつけたい!
・Instagramにも投稿したい!
と思い、これらを実装してみたので紹介しますー。
画像とテキストをシェアする!
通常UIActivityViewControllerを用いてシェアするときは以下のようにします。
//ボタンが押されたとき
func btnTapped(sender:UIButton){
let text = "シェアするテキスト"
let image = UIImage(named:"test.jpg")
let activityItem:[Any] = [text,image]
let activityVC = UIActivityViewController(activityItems: activityItem, applicationActivities: nil)
self.present(activityVC, animated: true, completion: nil)
}
UIActivityViewControllerのactivityItemsにシェアしたいテキストや画像やURL等が含まれた配列を渡します。
こちらも何かの参考になれば(【Swift】UIActivityで画像を複数枚同時に共有するとき【メモ】)
Instagramにシェアしたい!
先ほどのコードでの実装だと、このActivitiesのリストに出てきてくれません。
手っ取り早く投稿できるようにするには「単一画像」または「動画URL」のみをActivityItemsに渡してやります
//ボタンが押されたとき
func btnTapped(sender:UIButton){
let image = UIImage(named:"test.jpg")
let activityItem:[Any] = [image]
let activityVC = UIActivityViewController(activityItems: activityItem, applicationActivities: nil)
self.present(activityVC, animated: true, completion: nil)
}
これだとInstagramにも投稿できるようになります。 ちなみに動画は3秒以上でないとシェアできません。
でもこの場合、Twitterとかメールとか別のやつを選んだときにも「画像のみ」のシェアしかできません。 テキストも画像もシェアできるところでは、両方をシェアしたい。しかしこのUIActivityVC、開かれる前にアイテム渡しちゃうし、それに合わせてシェアできるものだけしか表示してくれない。(テキスト・画像を渡すとInstagramが表示されない。)
どうすればいいものか。色々試行錯誤して、ようやく実装できますた。ようやく本題です。
結局やりたいことは、 UIActivityVCが開かれたときには、「画像のみ」でシェアできるものを表示し、選択されたActivityがテキストも渡せるものなら、テキストと画像の両方を渡す といったことです。
UIActivityItemSourceを用いる!
まず渡したいアイテムそれぞれにUIActivityItemSourceプロトコルに適合したNSObjectのサブクラスでを作ります。
//渡したいテキスト
class TextActivityItem:NSObject,UIActivityItemSource{
}
//渡したい画像
class ImageActivityItem:NSObject,UIActivityItemSource{
}
まずは画像の方から。
初期化時にUIImageを渡すようにしておきます。
class ImageActivityItem:NSObject,UIActivityItemSource{
var image:UIImage?
override init(){
super.init()
}
convenience init(_ image:UIImage?){
self.init()
self.image = image
}
}
次にプレースホルダーの設定をします。
func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
return image ?? UIImage()
}
これは仮のアイテムで、UIImageをシェアするつもりだよ!っていうのが伝わればおkなやつです。実際に渡すアイテムと型が違っても一応おk。
このactivityViewControllerPlaceholderItem(_:)が結構肝です。これによってどのActivityが表示されるかが決まります。
最後に実際に渡したい値をセット。
func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivityType) -> Any? {
return image
}
ImageActivityItemはこんな感じになりました。
class ImageActivityItem:NSObject,UIActivityItemSource{
var image:UIImage?
override init(){
super.init()
}
convenience init(_ image:UIImage?){
self.init()
self.image = image
}
//実際に渡す
func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivityType) -> Any? {
return image
}
//仮に渡す
func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
return image ?? UIImage()
}
}
テキストを渡す
やりたいことは画像の時とほぼ同じです。UIImageかStringかの差です。
class TextActivityItem:NSObject,UIActivityItemSource{
var shareText = ""
override init(){
super.init()
}
convenience init(_ text:String){
self.init()
self.shareText = text
}
func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivityType) -> Any? {
return shareText
}
func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
//ここではNSObjectを返しておく
return NSObject()
}
}
この時の1番のキモがここ!
func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
//ここではNSObjectを返しておく
return NSObject()
}
ここではString型を返さず
実際にこれらを使うときは、
//ボタンが押されたとき
func btnTapped(sender:UIButton){
let text = "シェアするテキスト"
let image = UIImage(named:"test.jpg")
let activityItem:[Any] = [TextActivityItem(text),ImageActivityItem(image)]
let activityVC = UIActivityViewController(activityItems: activityItem, applicationActivities: nil)
self.present(activityVC, animated: true, completion: nil)
}
のようにして配列に入れて渡してやります。
activityViewControllerPlaceholderItem(_:)を設定がここで活用されます。
最初の方法(text,imageをそのまま渡す方法)だと、「String型とUIImage型」をシェアするためのActivityアイコンが並びます。
しかしこの方法では、TextActivityItemのところでPlaceholderItemにNSObject()を渡しているので、「NSObject型とUIImage型」をシェアするためのアイコンが並びます。
このおかげでString型を含んでいると出てこないはずのInstagramのアイコンも出てくるようになります。∩(〃・ω・〃)∩ ばんじゃーい
そして実際にActivityアイコンを選択した後に、activityViewController(_:itemForActivityType:)が呼び出され、実際に必要なモノだけを自動的に選んでシェアします。(Instagramには画像のみが渡されます。テキストは渡されません。)
Twitterへのシェア時にのみハッシュタグをつけよう!
Twitterへのシェアの時にだけハッシュタグをつけたい!という場合には、先ほど作ったTextActivityItemのactivityViewController(_:itemForActivityType:)で分岐してやります。
func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivityType) -> Any? {
//Twitter投稿時のみハッシュタグをつける
if activityType == .postToTwitter {
return shareText + "#ハッシュタグ"
}
return shareText
}
TextActivityItemの全体はこんな感じになりました。
class TextActivityItem:NSObject,UIActivityItemSource{
var shareText = ""
override init(){
super.init()
}
convenience init(_ text:String){
self.init()
self.shareText = text
}
func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivityType) -> Any? {
if activityType == .postToTwitter {
return shareText + "#ハッシュタグ"
}
return shareText
}
func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
//ここではNSObjectを返しておく
return NSObject()
}
}
おまけ。
Instagramのときだけ画像を加工したいとき
Twitterへの投稿にはactivityTypeに .postToTwitterというのが用意されていますが、Instagramでは用意されてません。ので以下のように分岐できます。
func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivityType) -> Any? {
if activityType.rawValue == "com.burbn.instagram.shareextension"{
//例えばここで真四角に切り取り処理をするとか。
return cropImage(image: image!, contentSize: CGSize(width:600,height:600))
}
return image
}
こんな感じでやってみても良いかも。
UIActivity関連これはうまくいったんですが、Facebookへの投稿だけ開いて少しすると勝手に閉じるし、謎エラーもあって結構困る・・・・。
それではでは。
参考リンク
Additional Notes追記
Gistにあげときました。
一応gistにあげました。
でも自分はもう使ってない手法。 TwitterKit等々を頑張って使ってます。
コメントはありません。
現在コメントフォームは工事中です。