UIActivityViewController的使用

UIActivityViewController的使用#

UIActivityViewController是iOS上為App實(shí)現(xiàn)多種服務(wù)的一個(gè)標(biāo)準(zhǔn)視圖控制器,系統(tǒng)默認(rèn)提供了很多的標(biāo)準(zhǔn)服務(wù),如拷貝鏈接,添加到Safari閱讀列表,還有就是多平臺(tái)的分享,包括微博,F(xiàn)acebook,email等。其實(shí)看起來(lái)就是一個(gè)actionSheet。

我們的任務(wù)是負(fù)責(zé)配置、顯示和關(guān)閉這個(gè)視圖控制器,配置也就是為這個(gè)視圖控制器提供數(shù)據(jù)源。當(dāng)然,我們也可以根據(jù)需要自定義自己服務(wù)(通過(guò)繼承UIActivity)。在iPad上,我們以popover的形式顯示這個(gè)視圖控制器;而在 iPhone 和 iPod touch上, 我們需要以模態(tài)的形式顯示。

先寫一個(gè)最基本的代碼:

    let image = UIImage(named: "iOS9")
    let str = "hello iOS9"
    let url = NSURL(string: "http://helloseed.io")
    let items:[AnyObject] = [image!, str, url!];
    
    self.presentViewController(vc, animated: true, completion: nil)
標(biāo)準(zhǔn)顯示

可以看到,幾句代碼就可以顯示出我們需要的controller了。Activity分為兩類,圖中可以看到它被分割線分為上下兩部分,上面部分為Share(Objective-C為UIActivityCategoryShare)類型,下面部分為Action(Objective-C為UIActivityCategoryAction)類型。

下面我們添加如下代碼:

    vc.completionWithItemsHandler = {(activityType:String?, completed:Bool, returnedItems:[AnyObject]?, activityError:NSError?) -> Void in
        if completed {
            self.alert("成功")
        }
        vc.completionWithItemsHandler = nil
    }

然后點(diǎn)擊其中的一個(gè)item,這時(shí)會(huì)彈出成功的alert。沒(méi)錯(cuò),這個(gè)block屬性就是用來(lái)處理點(diǎn)擊后的回調(diào)。

結(jié)果回調(diào)

幾個(gè)參數(shù)說(shuō)明:activityType為被點(diǎn)擊的服務(wù)類型;completed標(biāo)識(shí)服務(wù)是否執(zhí)行成功;returnedItems是一個(gè)包含NSExtensionItem對(duì)象的數(shù)組;activityError指出出錯(cuò)原因。更詳細(xì)的參數(shù)說(shuō)明可以參考官方文檔

現(xiàn)在,我們?cè)僭谡{(diào)用presentViewController方法之前添加一行代碼:

    vc.excludedActivityTypes = [UIActivityTypeMail, UIActivityTypeAddToReadingList, UIActivityTypeAssignToContact];

再次運(yùn)行,可以發(fā)現(xiàn)少了Mail、Assign to ContactAdd to Reading List這三個(gè)item。是的,excludedActivityTypes這個(gè)數(shù)組就是用來(lái)指定不需要那些服務(wù)的。我們可以將不需要的服務(wù)寫進(jìn)數(shù)組內(nèi),具體還有哪些服務(wù),見(jiàn)文檔。(注:現(xiàn)在所運(yùn)行的環(huán)境都是在iOS8上的,iOS9后還添加了Notes(備忘錄),和Reminders(提醒事項(xiàng))這兩個(gè)服務(wù))

取消顯示不必要是item

標(biāo)準(zhǔn)的基本上就這些,然并卵。。。
基本上,僅使用系統(tǒng)默認(rèn)提供的服務(wù)是不夠的,每個(gè)App有自己的需求,所以自定義服務(wù)是必然的。前面說(shuō)到,通過(guò)繼承UIActivity來(lái)實(shí)現(xiàn)自定義,下面來(lái)自定義幾個(gè)常用的服務(wù):微信Timeline,微信Session、新浪微博、拷貝鏈接。(這里就以微博和拷貝鏈接為例,其他都大同小異的)

  1. 先創(chuàng)建一個(gè)類名為:CustomActivity,繼承于UIActivity,以后其他自定義的Activity類直接繼承它。代碼如下:
import UIKit

class CustomActivity: UIActivity {
    var title:String?
    var image:UIImage?
    var url:NSURL?
    
    override class func activityCategory() -> UIActivityCategory {
        return .Share
    }
    
    override func activityType() -> String? {
        return NSStringFromClass(self.classForCoder)
    }
    
    /**
    返回是否可以執(zhí)行
    
    - parameter activityItems: 從調(diào)用處傳進(jìn)來(lái)的items,可以通過(guò)這個(gè)items里面存放的類型數(shù)據(jù)來(lái)判斷是否可以執(zhí)行
    
    - returns: 返回true,則這個(gè)activity就會(huì)在controller上出現(xiàn);否則,則不會(huì)出現(xiàn)
    */
    override func canPerformWithActivityItems(activityItems: [AnyObject]) -> Bool {
        //只要items有數(shù)據(jù),就返回true。
        if activityItems.count > 0 {
            return true
        }
        return false
    }
    
    /**
    準(zhǔn)備數(shù)據(jù)
    
    - parameter activityItems: 數(shù)據(jù)對(duì)象數(shù)組
    */
    override func prepareWithActivityItems(activityItems: [AnyObject]) {
        for activityItem in activityItems {
            if let title = activityItem as? String {
                self.title = title
            } else if let image = activityItem as? UIImage {
                self.image = image
            } else if let url = activityItem as? NSURL {
                self.url = url
            }
        }
    }
    
    /**
    執(zhí)行點(diǎn)擊
    */
//    override func performActivity() {
//        super.performActivity()

//        print(self.title)
//        print(self.image)
//        print(self.url)
//    }
}

幾個(gè)需要我們override的方法的作用已經(jīng)在注釋上說(shuō)明,就不多說(shuō)了。
接著,我們創(chuàng)建一個(gè)WeiboActivity,如下:

import UIKit

class WeiboActivity: CustomActivity {
    override func activityTitle() -> String? {
        return "新浪微博"
    }
    
    override func activityImage() -> UIImage? {
        return UIImage(named: "weibo")
    }
    
    override func performActivity() {
        super.performActivity()
        
        //將需要分享的數(shù)據(jù)通過(guò)微博SDK進(jìn)行分析
        
    }
}

然后創(chuàng)建一個(gè)CopyLinkActivity類,如下:

import UIKit

class CopyLinkActivity: CustomActivity {
    override class func activityCategory() -> UIActivityCategory {
        return .Action
    }
    
    override func activityTitle() -> String? {
        return "拷貝鏈接"
    }
    
    override func activityImage() -> UIImage? {
        return UIImage(named: "share_link")
    }
    
    override func canPerformWithActivityItems(activityItems: [AnyObject]) -> Bool {
    //因?yàn)槭强截愭溄?,所有如果不存在NSURL對(duì)象,則返回false
        for item in activityItems {
            if let _ = item as? NSURL {
                return true
            }
        }
        return false
    }
    
    override func performActivity() {
        super.performActivity()
        //拷貝需要的鏈接
    }
}

自定義工作告一段落,現(xiàn)在回到ViewController,將代碼改成如下:

    let image = UIImage(named: "seed")
    let str = "hello iOS9"
    let url = NSURL(string: "http://helloseed.io")
    let items:[AnyObject] = [image!, str, url!];

    let weibo = WeiboActivity()     //實(shí)例化WeiboActivity
    let copylink = CopyLinkActivity()   //實(shí)例化CopyLinkActivity

    let vc = UIActivityViewController(activityItems: items, applicationActivities: [weibo, copylink])
    vc.excludedActivityTypes = [UIActivityTypeMail, UIActivityTypeAddToReadingList, UIActivityTypeAssignToContact];
    self.presentViewController(vc, animated: true, completion: nil)

    vc.completionWithItemsHandler = {(activityType:String?, completed:Bool, returnedItems:[AnyObject]?, activityError:NSError?) -> Void in
        if completed {
            self.alert("成功")
        }
        vc.completionWithItemsHandler = nil
    }

執(zhí)行程序:


自定義Activity

順利完成。不過(guò)我們發(fā)現(xiàn),點(diǎn)擊自定義的activity后,不會(huì)調(diào)用completionWithItemsHandler方法,即沒(méi)有彈出成功。我的解決方法是,同樣自定義一個(gè)closure(Objective-C中的block)來(lái)執(zhí)行回調(diào)。于是,在CustomActivity中添加:

    var finishedBlock:(()-> Void)?

并將上面注釋掉的方法performActivity解注釋。如下:

    /**
    執(zhí)行點(diǎn)擊
    */
    override func performActivity() {
        super.performActivity()
        
        if let block = self.finishedBlock {
            block()
        }
        
        self.activityDidFinish(true)
    }

這樣,在調(diào)用處想執(zhí)行什么代碼直接添加到finishedBlock即可。
再啰嗦一下,其實(shí)我們可以連prepareWithActivityItems都不需要override,title,image,url也都不需要定義,CustomActivity的子類也不需要overrideperformActivity了。直接將要執(zhí)行的代碼放到finishedBlock上,類似這樣:

    /**
    執(zhí)行點(diǎn)擊
    */
    override func performActivity() {
        super.performActivity()
        
        if let block = self.finishedBlock {
            block()
        }
        
        self.activityDidFinish(true)
    }

最后,為Activity提供的圖片需要注意的一點(diǎn):如果Activity的Category是Share,則不能是透明的,即關(guān)閉透明通道;如果Category是Action,則圖片需要開(kāi)啟透明通道,因?yàn)橄到y(tǒng)需要將圖片渲染成和標(biāo)準(zhǔn)的一樣顏色(所以,不需要將圖片顏色調(diào)成一致,系統(tǒng)會(huì)幫我們做),另外,圓角也是系統(tǒng)處理的。

Demo: https://github.com/linshaolie/UIActivityViewControllerDemo

參考文章:
https://github.com/nixzhu/dev-blog/blob/master/2014-04-22-ui-activity-viewcontroller.md

想獲得第一手精彩文章,歡迎關(guān)注我的微信公眾號(hào):"iOS和Android干貨"

掃一掃發(fā)現(xiàn)更多精彩文章
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容