2016-12-05 14 views
0
問題

我一直在使用下面的代碼通過各種社交媒體應用程序調用UIActivityViewController共享貼紙:透明PNG在UIActivityViewController爲FB Messenger和iMessage的

if let image = sticker.getUIImage(), let imgData = UIImagePNGRepresentation(image) { 
    let activityVC = UIActivityViewController(activityItems: [imgData], applicationActivities: nil) 
    activityVC.popoverPresentationController?.sourceView = gesture.view 
    self.present(activityVC, animated: true, completion: nil) 
} else { 
    ErrorHandler.handleError(STICKER_IMAGE_NOT_FOUND, sticker) 
} 

該代碼已經工作正常,直到FB messenger的最新更新(版本98.0)。現在它顯示錯誤「無法加載內容」。 FB使者似乎更喜歡這樣的URL:

if let item = sticker.getImageURL() { 
    let activityVC = UIActivityViewController(activityItems: [item], applicationActivities: nil) 
    activityVC.popoverPresentationController?.sourceView = gesture.view 
    self.present(activityVC, animated: true, completion: nil) 
} else { 
    ErrorHandler.handleError(STICKER_IMAGE_NOT_FOUND, sticker) 
} 

這適用於FB Messenger,但iMessage顯示帶有黑色背景的透明PNG。 我在看UIActivityViewControllerCompletionWithItemsHandler,但討論表明它在活動之後運行,對於我需要做的事來說太晚了。我也嘗試創建一個自定義的UIActivity,爲activityType返回UIActivityType.message,但它被添加到控制器的底部,而不是接管默認值。

有沒有辦法在UIActivityViewController中攔截項目的選擇,這樣我可以使用MFMessageComposeViewController並將UIImagePNGRepresentation添加到消息並允許所有其他人使用該URL?

是否有一個特定的參數類型,我可以傳遞給UIActivityViewController,它將正確顯示所有社交應用程序的透明PNG?

TIA 邁克

回答

0

盤旋迴收這件事。我最終從通用的UIActivityViewController切換到定製每種服務類型的系統。我使用Bob de Graaf的BDGShare。我建立了應用程序支持的服務列表,爲每個服務顯示一個按鈕,然後顯示一個切換到每種類型的共享。萬一有人在研究這個,這是我想出了:

類型的共享應用程序要支持:

public enum ShareServiceType:Int { 
    case iMessage=0, facebook, twitter, instagram, whatsApp, facebookMessenger, email, more 
} 

類存儲有關共享服務的類型信息

public class ShareTargetVO: NSObject 
{ 
    var icon:String! 
    var label:String! 
    var type:ShareServiceType 

    init(serviceType:ShareServiceType, icon:String, label:String) 
    { 
     self.type = serviceType 
     self.icon = icon 
     self.label = label 
    } 
} 

在我的社交網絡輔助函數來填充可用服務的列表:

static func getShareTargetList(for sticker : ReeSticker) -> [ShareTargetVO] { 
    var services:Array<ShareTargetVO> = [] 

    // Check to see which capabilities are present and add buttons 
    if (BDGShare.shared().isAvailable(forServiceType: SLServiceTypeFacebook)) { 
     services.append(ShareTargetVO(serviceType: ShareServiceType.facebook, icon: "Icon-Share-Facebook", label: "Facebook")) 
    } 
    // Checking for facebook service type because there's no availability check with FBSDK for messenger (could be rolled into the lib) 
    if (BDGShare.shared().isAvailable(forServiceType: SLServiceTypeFacebook) && !sticker.type.doesContain("video")) { 
     services.append(ShareTargetVO(serviceType: ShareServiceType.facebookMessenger, icon: "Icon-Share-Messenger", label: "Messenger")) 
    } 
    if (BDGShare.shared().isAvailable(forServiceType: SLServiceTypeTwitter)) { 
     services.append(ShareTargetVO(serviceType: ShareServiceType.twitter, icon: "Icon-Share-Twitter", label: "Twitter")) 
    } 
    if (BDGShare.shared().canSendSMS()) { 
     services.append(ShareTargetVO(serviceType: ShareServiceType.iMessage, icon: "Icon-Share-Messages", label: "Messages")) 
    } 
    if UIApplication.shared.canOpenURL(URL(string: "whatsapp://")! as URL) && !sticker.type.contains("video") { 
     services.append(ShareTargetVO(serviceType: ShareServiceType.whatsApp, icon: "Icon-Share-Whatsapp", label: "What's App?")) 
    } 
    if UIApplication.shared.canOpenURL(URL(string: "instagram://app")! as URL) && !sticker.type.contains("video") { 
     services.append(ShareTargetVO(serviceType: ShareServiceType.instagram, icon: "Icon-Share-Instagram", label: "Instagram")) 
    } 
    if (BDGShare.shared().canSendEmail()) { 
     services.append(ShareTargetVO(serviceType: ShareServiceType.email, icon: "Icon-Share-Mail", label: "Email")) 
    } 
    services.append(ShareTargetVO(serviceType: ShareServiceType.more, icon: "Icon-Share-More", label: "More")) 

    return services 
} 

在我的視圖控制器的函數來填充按鈕的UICollectionView共享限制爲從列表中函數返回這些服務:

func layoutShareButtons() { 

    let f = self.view.frame 
    let btnWidth = f.width * 0.82 
    let bannerWidth = btnWidth + 10 

    mask = UIView(frame: CGRect(x: 0, y: 0, width: f.width, height: f.height)) 
    mask.backgroundColor = .black 
    mask.alpha = 0.3 
    self.view.addSubview(mask) 

    buttonList = SocialHelper.getShareTargetList(for: self.sticker) 

    let buttonGridLayout = UICollectionViewFlowLayout() 
    buttonGridLayout.sectionInset = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5) 
    buttonGridLayout.itemSize = CGSize(width: 60, height: 60) 
    buttonGridLayout.scrollDirection = .horizontal 

    buttonListView = UICollectionView(frame: CGRect(x: (f.width - bannerWidth)/2, 
                y: self.preview.frame.origin.y + self.preview.frame.height + 10, 
                width: bannerWidth, 
                height: 80), 
             collectionViewLayout: buttonGridLayout) 
    buttonListView.register(ShareButtonCell.self, forCellWithReuseIdentifier: "shareButtonCell") 
    buttonListView.dataSource = self 
    buttonListView.delegate = self 
    self.view.addSubview(buttonListView) 

    // cancel button for sharing view 
    // Button (added last to ensure it's on top of the z-order) 
    cancelButton = SimpleButton(frame: CGRect(x: (f.width - bannerWidth)/2, y: self.buttonListView.frame.origin.y + self.buttonListView.frame.height + 10, width: bannerWidth, height: 52)) 
    cancelButton.backgroundColor = UIColor(netHex:0x202020) 
    cancelButton.layoutComponent(0, label: "Cancel") 
    cancelButton.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.cancelButtonPressed(_:)))) 
    self.view.addSubview(self.cancelButton) 
} 

UICollectionView didSelect處理程序(根據您的應用程序更好的SoC刪除「份額「功能,一個單獨的類只是份額實現,在此應用程序,我們正在使用的屏幕是專門爲共享):

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 
    self.share(shareTarget: buttonList[indexPath.row]) 
} 

最後一個函數調用正確的共享類型:

func share(shareTarget: ShareTargetVO) { 

    // Params to submit to service 
    self.shareUrl = self.sticker.getStickerURL() 

    let textStr = "" // BDGShare supports a message passed in as well but we just send the sticker 

    // we need the NSData either way (sticker/video) 
    var ok = true 
    // try? is fine here because result is tested below 
    let urlData : Data? = try? Data(contentsOf: self.shareUrl as URL) 
    ok = (urlData != nil) 
    var img: UIImage? = nil 
    // if it's an image type then get it 
    if ok { 
     if (self.shareUrl.pathExtension.contains("png")) || (self.shareUrl.pathExtension.contains("jpg")) { 
      img = UIImage(data: urlData! as Data) 
      ok = (img != nil) 
     } 
    } 

    if !ok { 
     let alertCtrl = UIAlertController(title: "Error sending", message: "There was an error gathering the information for sending this sticker.", preferredStyle: .alert) 
     alertCtrl.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil)) 
     self.present(alertCtrl, animated: true, completion: nil) 
     return 
    } 

    switch shareTarget.type 
    { 
    case .iMessage: 
     BDGShare.shared().shareSMS(textStr, recipient: nil, image: img, data:urlData! as Data, imageName: "sendSticker.png", completion: {(SharingResult) -> Void in 
      // Handle share result... 
      self.handleShareResult(shareTarget.type, shareResult: SharingResult) 
     }) 
     break 

    case .facebook: 
     BDGShare.shared().shareFacebook("", urlStr: "", image: img, completion: {(SharingResult) -> Void in 
      // Handle share result... 
      self.handleShareResult(shareTarget.type, shareResult: SharingResult) 
     }) 
     break 

    case .twitter: 
    ... more code for handling each type of share 
    } 
} 

所以我使用BDGShare來實現UIActivityViewController。順便說一句 - 列表末尾的「更多」選項會調用該UIActivityViewController,因此如果用戶願意,它仍然可供用戶使用。

HTH,Mike