如何从已有的UIActivityType获取UIActivity以构建UIActivityViewController?
首先得明确一个关键点:系统自带的那些UIActivityType(比如.message、.mail这类),你没法直接通过Type拿到对应的UIActivity实例。因为这些系统活动都是UIActivityViewController内部自动创建和管理的,Apple并没有把它们的初始化接口开放给开发者,咱们没法手动实例化系统的这些活动。
再看你写的代码,这里有个明显的错误:applicationActivities: [MyActivity(),"TypeUIActivity"]里的字符串"TypeUIActivity"是不能直接放进去的,applicationActivities数组要求的必须是UIActivity类型的实例,字符串根本不兼容哦。
下面给你几个可行的解决方案:
方案1:想显示系统默认活动?不用手动添加
UIActivityViewController会自动根据你传入的activityItems类型,自动匹配并展示合适的系统活动。比如你传了一张图片,它会自动显示“保存到相册”“分享到微信”(如果用户装了微信)这些系统支持的选项。要是你想只展示特定的系统活动,不用手动添加,反而可以用excludedActivityTypes属性把不需要的活动排除掉,剩下的就是你想要的了。举个例子:
let activityItems = ["我是要分享的文本"] let customActivity = MyActivity() let activityViewController = UIActivityViewController(activityItems: activityItems, applicationActivities: [customActivity]) // 排除掉不需要的系统活动,比如不想显示Facebook和Twitter分享 activityViewController.excludedActivityTypes = [.postToFacebook, .postToTwitter] present(activityViewController, animated: true, completion: nil)
方案2:想要类似系统活动的自定义功能?自己写一个
如果你是想实现一个和某个UIActivityType功能近似的自定义活动,那可以自己继承UIActivity来实现。比如你想做一个类似系统“信息”的分享功能,步骤大概是这样:
- 新建类继承自UIActivity
- 重写
activityType(可以返回自定义的Type,或者系统的Type,但返回系统Type也不会替换原有的系统活动,只是作为标识) - 重写
activityTitle和activityImage来设置活动的标题和图标 - 重写
canPerform(withActivityItems:)判断当前的活动数据是否支持这个自定义活动 - 重写
prepare(withActivityItems:)来准备分享需要的数据 - 重写
perform()来执行具体的分享逻辑,完成后记得调用activityDidFinish(true)
给你个简单的示例代码:
class CustomMessageActivity: UIActivity { // 设置活动类型,这里返回系统的.message只是标识,不会替换系统的信息活动 override var activityType: UIActivity.ActivityType? { return .message } // 活动标题 override var activityTitle: String? { return "自定义信息分享" } // 活动图标 override var activityImage: UIImage? { return UIImage(systemName: "message.fill") } // 判断是否支持当前的分享数据 override func canPerform(withActivityItems activityItems: [Any]) -> Bool { // 这里判断是否有可分享的文本或图片 return activityItems.contains(where: { $0 is String || $0 is UIImage }) } // 准备分享数据 override func prepare(withActivityItems activityItems: [Any]) { // 这里可以提取需要分享的内容,比如把文本存起来 } // 执行分享逻辑 override func perform() { // 这里写你自定义的分享逻辑,比如跳转到信息应用 // 完成后必须调用这个方法告诉系统活动结束了 activityDidFinish(true) } }
使用的时候就像你原来的思路一样,把自定义的实例传进去:
let customMsgActivity = CustomMessageActivity() let activityViewController = UIActivityViewController(activityItems: ["Hello 自定义分享"], applicationActivities: [MyActivity(), customMsgActivity]) present(activityViewController, animated: true)
最后再梳理下重点
- 系统默认活动没法通过UIActivityType获取实例,都是UIActivityViewController自动管理的
- 控制系统活动显示,用
excludedActivityTypes排除不需要的更靠谱 - 要自定义活动,必须继承UIActivity实现对应的方法,不能直接传字符串当实例
内容的提问来源于stack exchange,提问作者Reimond Hill

