UIActivityViewController的使用

UIActivityViewController的使用

UIActivityViewController是iOS上为App实现多种服务的一个标准视图控制器,系统默认提供了很多的标准服务,如拷贝链接,添加到Safari阅读列表,还有就是多平台的分享,包括微博,Facebook,email等。其实看起来就是一个actionSheet。

我们的任务是负责配置、显示和关闭这个视图控制器,配置也就是为这个视图控制器提供数据源。当然,我们也可以根据需要自定义自己服务(通过继承UIActivity)。在iPad上,我们以popover的形式显示这个视图控制器;而在 iPhone 和 iPod touch上, 我们需要以模态的形式显示。

先写一个最基本的代码:

    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属性就是用来处理点击后的回调。
结果回调

几个参数说明:activityType为被点击的服务类型;completed标识服务是否执行成功;returnedItems是一个包含NSExtensionItem对象的数组;activityError指出出错原因。更详细的参数说明可以参考官方文档

现在,我们再在调用presentViewController方法之前添加一行代码:

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

再次运行,可以发现少了MailAssign to ContactAdd to Reading List这三个item。是的,excludedActivityTypes这个数组就是用来指定不需要那些服务的。我们可以将不需要的服务写进数组内,具体还有哪些服务,见文档。(注:现在所运行的环境都是在iOS8上的,iOS9后还添加了Notes(备忘录),和Reminders(提醒事项)这两个服务)
取消显示不必要是item
标准的基本上就这些,然并卵。。。
基本上,仅使用系统默认提供的服务是不够的,每个App有自己的需求,所以自定义服务是必然的。前面说到,通过继承UIActivity来实现自定义,下面来自定义几个常用的服务:微信Timeline,微信Session、新浪微博、拷贝链接。(这里就以微博和拷贝链接为例,其他都大同小异的)
1. 先创建一个类名为: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)
    }

    /**
    返回是否可以执行

    - parameter activityItems: 从调用处传进来的items,可以通过这个items里面存放的类型数据来判断是否可以执行

    - returns: 返回true,则这个activity就会在controller上出现;否则,则不会出现
    */
    override func canPerformWithActivityItems(activityItems: [AnyObject]) -> Bool {
        //只要items有数据,就返回true。
        if activityItems.count > 0 {
            return true
        }
        return false
    }

    /**
    准备数据

    - parameter activityItems: 数据对象数组
    */
    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
            }
        }
    }

    /**
    执行点击
    */
//    override func performActivity() {
//        super.performActivity()

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

几个需要我们override的方法的作用已经在注释上说明,就不多说了。
接着,我们创建一个WeiboActivity,如下:

import UIKit

class WeiboActivity: CustomActivity {
    override func activityTitle() -> String? {
        return "新浪微博"
    }

    override func activityImage() -> UIImage? {
        return UIImage(named: "weibo")
    }

    override func performActivity() {
        super.performActivity()

        //将需要分享的数据通过微博SDK进行分析

    }
}

然后创建一个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()
        //拷贝需要的链接
    }
}

自定义工作告一段落,现在回到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
    }

执行程序:
自定义Activity

顺利完成。不过我们发现,点击自定义的activity后,不会调用completionWithItemsHandler方法,即没有弹出成功。我的解决方法是,同样自定义一个closure(Objective-C中的block)来执行回调。于是,在CustomActivity中添加:

    var finishedBlock:(()-> Void)?

并将上面注释掉的方法performActivity解注释。如下:

    /**
    执行点击
    */
    override func performActivity() {
        super.performActivity()

        if let block = self.finishedBlock {
            block()
        }

        self.activityDidFinish(true)
    }

这样,在调用处想执行什么代码直接添加到finishedBlock即可。
再啰嗦一下,其实我们可以连prepareWithActivityItems都不需要override,title,image,url也都不需要定义,CustomActivity的子类也不需要overrideperformActivity了。直接将要执行的代码放到finishedBlock上,类似这样:

    /**
    执行点击
    */
    override func performActivity() {
        super.performActivity()

        if let block = self.finishedBlock {
            block()
        }

        self.activityDidFinish(true)
    }

最后,为Activity提供的图片需要注意的一点:如果Activity的Category是Share,则不能是透明的,即关闭透明通道;如果Category是Action,则图片需要开启透明通道,因为系统需要将图片渲染成和标准的一样颜色(所以,不需要将图片颜色调成一致,系统会帮我们做),另外,圆角也是系统处理的。

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值