如何从UIActivityViewController中排除笔记和提醒应用程序?

57

我正在创建一个UIActivityViewController并将StringURL传递给它。这显然会配置UIActivityViewController使用一些我想排除的项目(我的目标是分享我的应用程序信息)。

我已经成功地通过设置适当的excludedActivityTypes来排除了许多系统提供的活动(例如“添加到阅读列表”)。

但是,我无法排除提醒和备忘录应用程序。有人能建议一种方法吗?这些应用程序出现在列表的第三和第四位,因此使得Twitter和Facebook不可见,除非用户滚动。

9个回答

57
如果您不想子类化 UIActivityViewController,可以在创建 UIActivityViewController 时将它们包含在 .excludedActivityTypes 中。
Objective C:
UIActivityViewController *activityController = [[UIActivityViewController alloc]initWithActivityItems:sharingItems applicationActivities:nil];
activityController.excludedActivityTypes = @[
    UIActivityTypeAssignToContact,
    UIActivityTypePrint,
    UIActivityTypeAddToReadingList,
    UIActivityTypeSaveToCameraRoll,
    UIActivityTypeOpenInIBooks,
    @"com.apple.mobilenotes.SharingExtension",
    @"com.apple.reminders.RemindersEditorExtension"
];
[self presentViewController:activityController animated:YES completion:nil];

Swift 4.2:

let activityController = UIActivityViewController(activityItems: sharingItems, applicationActivities: nil)
activityController.excludedActivityTypes = [
    UIActivity.ActivityType.assignToContact,
    UIActivity.ActivityType.print,
    UIActivity.ActivityType.addToReadingList,
    UIActivity.ActivityType.saveToCameraRoll,
    UIActivity.ActivityType.openInIBooks,
    UIActivity.ActivityType(rawValue: "com.apple.reminders.RemindersEditorExtension"),
    UIActivity.ActivityType(rawValue: "com.apple.mobilenotes.SharingExtension")]
present(activityController, animated: true, completion: nil)

1
哎呀,在Swift 3、Xcode 8.1和iOS 9.3中不起作用。提醒事项活动仍然出现在共享表中。 - Womble
我可以通过这种方法在iOS 10.3中排除“笔记”应用程序,但正如@Womble所说,在iOS 9.3上它不起作用。 - Jonny
4
对我来说在iOS 10.3上运行良好。 - allocate
4
适用于iOS 11。这应该是现在被接受的答案。 - Siegfoult
2
对于iOS 13,请使用.init(rawValue: "com.apple.reminders.sharingextension") - James
显示剩余4条评论

35

Swift 2.2版本。在iOS9.3上进行了测试,可用。

更新并已经通过App Store审核。

import UIKit

class ActivityViewController: UIActivityViewController {

    func _shouldExcludeActivityType(activity: UIActivity) -> Bool {
        let activityTypesToExclude = [
            "com.apple.reminders.RemindersEditorExtension",
            "com.apple.mobilenotes.SharingExtension",
            UIActivityTypeOpenInIBooks,
            UIActivityTypePrint,
            UIActivityTypeAssignToContact,
            "com.google.Drive.ShareExtension"
        ]

        if let actType = activity.activityType() {
            if activityTypesToExclude.contains(actType) {
                return true
            }
            else if super.excludedActivityTypes != nil {
                return super.excludedActivityTypes!.contains(actType)
            }
        }
        return false
    }

}

同样有用

 "com.apple.mobileslideshow.StreamShareService"

去除了“云”状物。

输入图像描述


你成功地使用这段代码获得了苹果公司的应用程序批准吗? :) - Andriy Gordiychuk
还不知道。大约一周后提交。有一点希望,因为似乎danielbmarques使用objC版本获得了批准(请参见顶部答案中的评论)。 - guido
2
苹果审核刚批准了我的应用程序,并将其发布。 - guido
非常棒且有用的回答 - 非常感谢。正在发送赏金。 - Fattie
我很好奇,你是如何找到哪个字符串类型对应哪个应用程序按钮的?例如,如何找到Dropbox的字符串类型?此外,是否有一种方法可以获取在设备中注册的所有活动的列表? - GeneCode
2
老实说我不记得了,但我想如果你将 actType 打印到控制台上,它会给出所有显示应用程序的字符串。 - guido

21

有一种方式,但需要使用私有API

有时候苹果会有例外,特别是如果你修复了一个bug。

让我们深入细节...


UIActivityViewController有一个名为"_availableActivitiesForItems:"的私有方法,该方法返回一个UISocialActivity对象数组。

UISocialActivity有一个有趣的属性,叫做"activityType",它返回一个域格式的活动类型。

经过一些测试,我成功地发现了提醒和笔记的活动类型:

  • com.apple.reminders.RemindersEditorExtension
  • com.apple.mobilenotes.SharingExtension

不幸的是,将这两个类型传递给".excludedActivityTypes"并没有任何区别。

"_availableActivitiesForItems:"拯救了一切!

旧的方法:

更新:我找到了一个更好的方法来实现它。

我发布的第一个解决方案在某些情况下不起作用,因此不应被认为是稳定的。

头文件:

#import <UIKit/UIKit.h>

@interface UISocialActivity : NSObject

- (id)activityType;

@end

@interface UIActivityViewController (Private)

- (id)_availableActivitiesForItems:(id)arg1;

@end

@interface ActivityViewController : UIActivityViewController

@end

实现:

@implementation ActivityViewController

- (id)_availableActivitiesForItems:(id)arg1
{
    id activities = [super _availableActivitiesForItems:arg1];
    NSMutableArray *filteredActivities = [NSMutableArray array];

    [activities enumerateObjectsUsingBlock:^(UISocialActivity*  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {

        if (![[obj activityType] isEqualToString:@"com.apple.reminders.RemindersEditorExtension"] &&
            ![[obj activityType] isEqualToString:@"com.apple.mobilenotes.SharingExtension"]) {
            [filteredActivities addObject:obj];
        }

    }];

    return [NSArray arrayWithArray:filteredActivities];
    }
    @end

新方式:

标题:

@interface UIActivityViewController (Private)

- (BOOL)_shouldExcludeActivityType:(UIActivity*)activity;

@end

@interface ActivityViewController : UIActivityViewController

@end

实现:

@implementation ActivityViewController

- (BOOL)_shouldExcludeActivityType:(UIActivity *)activity
{
    if ([[activity activityType] isEqualToString:@"com.apple.reminders.RemindersEditorExtension"] ||
        [[activity activityType] isEqualToString:@"com.apple.mobilenotes.SharingExtension"]) {
        return YES;
    }
    return [super _shouldExcludeActivityType:activity];
}

@end

"非法",但它可以工作。

如果能够通过苹果验证就太好了。


2
非常感谢!我会尝试一下并告诉你是否通过验证! - Andriy Gordiychuk
2
@AndriyGordiychuk,我想知道你是否已经得到了答案,它是否通过了苹果的验证。 :) - Paulo Miguel Almeida
5
@Paulo 我的应用程序刚刚通过了这个。 - dbmrq
2
更新:Swift 3 把它搞崩了。 - dbmrq
1
@MatteoPacini 感谢您的出色工作。这对我很有帮助,我希望应用商店不会拒绝我的应用程序。再次感谢,省了我好几个小时。 - Pratik Jamariya
显示剩余3条评论

9
在2019年看到这篇帖子的任何人,提醒事项扩展程序的关键已经随着iOS 13改变,现在是:
(rawValue: "com.apple.reminders.sharingextension")

6

由于在Apple文档中,笔记和提醒事项并没有声明为UIActivities,因此您无法将它们排除在外。这只是iOS9的一个问题,希望苹果公司能够提供此选项。目前已声明的UIActivities包括:

UIActivityTypePostToFacebook, 
UIActivityTypePostToTwitter, 
UIActivityTypePostToWeibo, 
UIActivityTypeMessage, 
UIActivityTypeMail, 
UIActivityTypePrint, 
UIActivityTypeCopyToPasteboard, 
UIActivityTypeAssignToContact,
UIActivityTypeSaveToCameraRoll,
UIActivityTypeAddToReadingList,
UIActivityTypePostToFlickr,
UIActivityTypePostToVimeo,
UIActivityTypePostToTencentWeibo,
UIActivityTypeAirDrop

  1. 当然它们被声明为UIActivities。问题在于相应的UIActivityType未包含在内。
  2. 建议认为一个月前提出的问题是今天提出的问题的重复,这是毫无意义的 :)
我知道目前没有使用标准方法排除这些项目的可能性。但是,可能有人知道一些技巧。如果没有,苹果公司最终会解决这个问题,并且回答这个问题的人(以及收藏它的人)将得到通知 :)
- Andriy Gordiychuk

2

对于Swift3+,不需要使用任何私有API hacks。只需在UIActivityViewController上使用公共的“excludedTypes”数组即可。由于这些没有UIActivityType(因为它们是Apple的内置扩展),因此您需要通过字符串引用它。您也可以使用此格式来处理任何第三方共享扩展。

例如:

let avc = UIActivityViewController(activityItems: ["my item"], applicationActivities: nil)
avc.excludedActivityTypes = [ .copyToPasteboard, 
    UIActivityType(rawValue: "com.apple.reminders.RemindersEditorExtension"),
    UIActivityType(rawValue: "com.apple.mobilenotes.SharingExtension") ]

avc.completionWithItemsHandler = { (activity, success, items, error) in
        print("AVC finished \(success) \(activity as Optional) \(items as Optional) \(error as Optional)")
    }
present(avc, animated: true, completion: nil)

这对于某些共享扩展很有帮助并且有效,但似乎对其他扩展无效:请参见@eranmarom在https://dev59.com/rY_ea4cB1Zd3GeqPIgON的答案。 - CKP78

2

谢谢您!在Xcode 8.1,Swift 3中,我能够使用以下代码获取:

UIActivityType(rawValue: "com.apple.reminders.RemindersEditorExtension"), UIActivityType(rawValue: "com.apple.mobilenotes.SharingExtension"),


1

我发现唯一的方法是创建自己的定制活动,直接将参数传递给它们(不通过活动表),然后通过活动表传递一些随机变量(不是字符串、URL、图像)。

MyCustomPinterestShareActivity* pinterest = [[MyCustomPinterestShareActivity alloc] init];
MyCustomFacebookGroupsActivity* facebook = [[MyCustomFacebookGroupsActivity alloc] init];
MyCustomInstagramActivity* instagram = [[MyCustomInstagramActivity alloc] init];

NSArray *activities = @[facebook,instagram,pinterest];

NSArray *activityItems = @[someVarThatCanBeWhateverTypeJustNotStringURLOrImg];

UIActivityViewController *activityView = [[UIActivityViewController alloc] initWithActivityItems:activityItems
                                                                           applicationActivities:activities];

但是,如果你无法使用任何功能,为什么要首先使用ActivityViewController呢...希望很快会有更好的解决方案


1

我无法像Matteo Pacini建议的那样将_shouldExcludeActivityType发送给Super,但这是我能够解决这个问题的方法:

@interface CustomActivityViewController()

- (BOOL)_shouldExcludeActivityType:(UIActivity *)activity;

@end

@implementation CustomActivityViewController

(...)

- (BOOL)_shouldExcludeActivityType:(UIActivity *)activity{

    if([[activity activityType]   isEqualToString:@"com.apple.reminders.RemindersEditorExtension"] || [[activity activityType] isEqualToString:@"com.apple.mobilenotes.SharingExtension"]){

    return YES;
}

    return [[super excludedActivityTypes]containsObject:activity.activityType];

 }

有没有在Swift中实现这个的方法? - user3561494

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接