UIActivityViewController的使用#
UIActivityViewController
是iOS上為App實現(xiàn)多種服務(wù)的一個標(biāo)準(zhǔn)視圖控制器,系統(tǒng)默認(rèn)提供了很多的標(biāo)準(zhǔn)服務(wù)病附,如拷貝鏈接,添加到Safari閱讀列表隙赁,還有就是多平臺的分享墨礁,包括微博充石,F(xiàn)acebook,email等峻厚。其實看起來就是一個actionSheet响蕴。
我們的任務(wù)是負(fù)責(zé)配置、顯示和關(guān)閉這個視圖控制器目木,配置也就是為這個視圖控制器提供數(shù)據(jù)源换途。當(dāng)然,我們也可以根據(jù)需要自定義自己服務(wù)(通過繼承UIActivity)刽射。在iPad上军拟,我們以popover的形式顯示這個視圖控制器;而在 iPhone 和 iPod touch上, 我們需要以模態(tài)的形式顯示誓禁。
先寫一個最基本的代碼:
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)
可以看到懈息,幾句代碼就可以顯示出我們需要的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
}
然后點擊其中的一個item俗慈,這時會彈出成功的alert姑宽。沒錯,這個block屬性就是用來處理點擊后的回調(diào)闺阱。
幾個參數(shù)說明:activityType
為被點擊的服務(wù)類型炮车;completed
標(biāo)識服務(wù)是否執(zhí)行成功;returnedItems
是一個包含NSExtensionItem
對象的數(shù)組;activityError
指出出錯原因瘦穆。更詳細(xì)的參數(shù)說明可以參考官方文檔
現(xiàn)在纪隙,我們再在調(diào)用presentViewController
方法之前添加一行代碼:
vc.excludedActivityTypes = [UIActivityTypeMail, UIActivityTypeAddToReadingList, UIActivityTypeAssignToContact];
再次運行,可以發(fā)現(xiàn)少了Mail扛或、Assign to Contact绵咱、Add to Reading List這三個item。是的熙兔,excludedActivityTypes
這個數(shù)組就是用來指定不需要那些服務(wù)的悲伶。我們可以將不需要的服務(wù)寫進(jìn)數(shù)組內(nèi),具體還有哪些服務(wù)黔姜,見文檔拢切。(注:現(xiàn)在所運行的環(huán)境都是在iOS8上的,iOS9后還添加了Notes(備忘錄)秆吵,和Reminders(提醒事項)這兩個服務(wù))
標(biāo)準(zhǔn)的基本上就這些,然并卵五慈。纳寂。。
基本上泻拦,僅使用系統(tǒng)默認(rèn)提供的服務(wù)是不夠的毙芜,每個App有自己的需求,所以自定義服務(wù)是必然的争拐。前面說到腋粥,通過繼承
UIActivity
來實現(xiàn)自定義,下面來自定義幾個常用的服務(wù):微信Timeline架曹,微信Session隘冲、新浪微博、拷貝鏈接绑雄。(這里就以微博和拷貝鏈接為例展辞,其他都大同小異的)
- 先創(chuàng)建一個類名為:
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)來的items,可以通過這個items里面存放的類型數(shù)據(jù)來判斷是否可以執(zhí)行
- returns: 返回true脚粟,則這個activity就會在controller上出現(xiàn)覆旱;否則,則不會出現(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ù)對象數(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í)行點擊
*/
// override func performActivity() {
// super.performActivity()
// print(self.title)
// print(self.image)
// print(self.url)
// }
}
幾個需要我們override的方法的作用已經(jīng)在注釋上說明,就不多說了。
接著画舌,我們創(chuàng)建一個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ù)通過微博SDK進(jìn)行分析
}
}
然后創(chuàng)建一個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 {
//因為是拷貝鏈接曲聂,所有如果不存在NSURL對象霹购,則返回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() //實例化WeiboActivity
let copylink = CopyLinkActivity() //實例化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í)行程序:
順利完成齐疙。不過我們發(fā)現(xiàn),點擊自定義的activity后旭咽,不會調(diào)用completionWithItemsHandler
方法贞奋,即沒有彈出成功。我的解決方法是穷绵,同樣自定義一個closure(Objective-C中的block)來執(zhí)行回調(diào)轿塔。于是,在CustomActivity
中添加:
var finishedBlock:(()-> Void)?
并將上面注釋掉的方法performActivity
解注釋仲墨。如下:
/**
執(zhí)行點擊
*/
override func performActivity() {
super.performActivity()
if let block = self.finishedBlock {
block()
}
self.activityDidFinish(true)
}
這樣勾缭,在調(diào)用處想執(zhí)行什么代碼直接添加到finishedBlock
即可。
再啰嗦一下目养,其實我們可以連prepareWithActivityItems
都不需要override俩由,title
,image
,url
也都不需要定義,CustomActivity
的子類也不需要overrideperformActivity
了癌蚁。直接將要執(zhí)行的代碼放到finishedBlock
上幻梯,類似這樣:
/**
執(zhí)行點擊
*/
override func performActivity() {
super.performActivity()
if let block = self.finishedBlock {
block()
}
self.activityDidFinish(true)
}
最后,為Activity提供的圖片需要注意的一點:如果Activity的Category是Share努释,則不能是透明的碘梢,即關(guān)閉透明通道;如果Category是Action洽洁,則圖片需要開啟透明通道痘系,因為系統(tǒng)需要將圖片渲染成和標(biāo)準(zhǔn)的一樣顏色(所以,不需要將圖片顏色調(diào)成一致饿自,系統(tǒng)會幫我們做)汰翠,另外,圓角也是系統(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)注我的微信公眾號:"iOS和Android干貨"