UIActivityViewController如何筛选分享目标应用?含Garmin Drive适配问题
UIActivityViewController 筛选分享应用机制及Garmin Drive适配方案
核心筛选机制
UIActivityViewController 筛选分享目标应用的流程分为两步:
- 初始候选池筛选:系统会收集所有 Activity Item 的**占位符(Placeholder)**对应的UTI集合,然后匹配系统中支持这些UTI的应用。只有能处理至少一个UTI的应用才会进入候选列表。
- 应用兼容性验证:针对每个候选应用,系统会逐一检查该应用是否能处理每个 Activity Item 针对它返回的UTI(通过
UIActivityItemSource的dataTypeIdentifierForActivityType:方法获取)。如果有任意一个Item的UTI不被应用支持,该应用会被从列表中移除。
你的问题根因
你用UIActivityItemSource后Garmin Drive消失,大概率是两个原因:
- 占位符返回的是字符串而非GPX文件URL,导致初始筛选阶段系统识别不到
com.topografix.gpx这个UTI,Garmin Drive直接被排除在候选池外。 - 即使你在
dataTypeIdentifierForActivityType:中返回了正确UTI,但如果占位符的UTI不匹配,系统不会触发后续针对Garmin Drive的兼容性验证。
解决方案
实现UIActivityItemSource时,必须保证占位符、返回内容、UTI三者对应匹配,针对不同应用返回不同数据:
代码实现示例
@interface GPXShareItemSource : NSObject <UIActivityItemSource> @property (nonatomic, strong) NSURL *localGPXURL; // 本地GPX文件的file:// URL @property (nonatomic, copy) NSString *shareText; @end @implementation GPXShareItemSource // 占位符必须返回GPX URL,让系统初始筛选时识别到com.topografix.gpx UTI - (id)activityViewControllerPlaceholderItem:(UIActivityViewController *)activityViewController { return self.localGPXURL; } // 针对不同应用返回对应数据 - (id)activityViewController:(UIActivityViewController *)activityViewController itemForActivityType:(UIActivityType *)activityType { if ([self isGarminDriveActivity:activityType]) { return self.localGPXURL; } else { return self.shareText; } } // 针对不同应用返回对应UTI - (NSString *)activityViewController:(UIActivityViewController *)activityViewController dataTypeIdentifierForActivityType:(UIActivityType *)activityType { if ([self isGarminDriveActivity:activityType]) { return @"com.topografix.gpx"; } else { return @"public.plain-text"; } } // 判断是否为Garmin Drive应用 - (BOOL)isGarminDriveActivity:(UIActivityType)activityType { // 方式1:通过自定义ActivityType判断(如果Garmin Drive注册了) if ([activityType isEqualToString:@"com.garmin.drive.share"]) { return YES; } // 方式2:通过OpenIn类应用的URL Scheme判断(需在Info.plist配置LSApplicationQueriesSchemes) NSURL *garminSchemeURL = [NSURL URLWithString:@"garmin-drive://"]; return [[UIApplication sharedApplication] canOpenURL:garminSchemeURL]; } @end
使用方式
GPXShareItemSource *itemSource = [[GPXShareItemSource alloc] init]; itemSource.localGPXURL = [NSURL fileURLWithPath:@"/path/to/your.gpx"]; itemSource.shareText = @"分享的位置信息文本"; UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:@[itemSource] applicationActivities:nil]; [self presentViewController:activityVC animated:YES completion:nil];
关键注意事项
- 必须使用本地文件URL(
file://开头),Garmin Drive通常不支持远程URL分享。 - 占位符的类型要和实际返回的Item类型一致:如果给Garmin Drive返回URL,占位符也必须是URL,否则系统无法识别对应的UTI。
- 若使用
UIActivityItemsConfiguration,逻辑和UIActivityItemSource一致,只需在activityItemsConfiguration:dataTypeIdentifiersForActivityType:中返回对应UTI即可。
内容的提问来源于stack exchange,提问作者Rog
相关产品推荐
相关产品推荐

