前言

背景:在iOS14中,如果APP读取剪切版的内容时,手机会弹出提示,提示哪个APP在获取剪切板内容。

iOS小技能:iOS14 读取用户剪切板数据弹出提示的兼容方案_掘金·日新计划

读取​​UIPasteboard​​​的​​string​​​、​​strings​​​、​​URL​​​、​​URLs​​​、​​image​​​、​​images​​​、​​color​​​、​​colors​​​的时候会触发系统提示。 使用​​hasStrings​​​、​​hasURLs​​​、​​hasImages​​​、​​hasColors​​等方法的时候不会触发系统提示。

  • 读取剪贴板的代码
  • iOS小技能:iOS14 读取用户剪切板数据弹出提示的兼容方案_插入图片_02

像这种第三方SDK,及时联系对应的SDK开发者。比如极光的v3.3.6就及时进行了适配

iOS小技能:iOS14 读取用户剪切板数据弹出提示的兼容方案_掘金·日新计划_03

在这里插入图片描述

划重点

  • 先判断剪切板内容的各式,如果符合规则才读取剪切板
  • 查找哪些SDK使用了剪切板,及时升级SDK。

比如发现了JCore SDK在iOS 14引用剪贴板,该行为导致APP被用户怀疑隐私泄露,请予以重视

I、弹出提示的兼容方案:尽可能少的去调用会触发系统提示的方法

弹出提示的原因:使用 UIPasteboard 访问用户数据

方案一:先判断剪切板内容的格式,如果符合规则采取读取。

例如app读取口令时判断是否符合数字和链接的规则

​iOS14 剪切板适配案例分析:读取口令的实现方法​

​kunnan.blog.csdn.net/article/det…​

方案二:使用​​changeCount​​来记录剪切板的数据是否发生变化

1.1 先判断剪切板内容的各式,如果符合规则才读取剪切板(例如淘宝的淘口令)

​如果应用仅仅访问只访问URL格式的剪切板内容,或者特定规则的内容,比如淘口令,就可以使用API先判断,确实是符合规则的时候再去读取​

判断是否为URL格式: UIPasteboardDetectionPatternAPI

typedef NSString * UIPasteboardDetectionPattern NS_TYPED_ENUM API_AVAILABLE(ios(14.0));

/// NSString value, suitable for implementing "Paste and Go"
UIKIT_EXTERN UIPasteboardDetectionPattern const UIPasteboardDetectionPatternProbableWebURL API_AVAILABLE(ios(14.0));

/// NSString value, suitable for implementing "Paste and Search"
UIKIT_EXTERN UIPasteboardDetectionPattern const UIPasteboardDetectionPatternProbableWebSearch API_AVAILABLE(ios(14.0));

/// NSNumber value
UIKIT_EXTERN UIPasteboardDetectionPattern const UIPasteboardDetectionPatternNumber API_AVAILABLE(ios(14.0));

下面 API 可以获得具体的 URL 信息,但是会触发剪切板提示。并且实测当用户剪切板中包含多个 URL 时只会返回第一个。

// Detection

/// Detects patterns in the first pasteboard item.
///
/// @param patterns Detect only these patterns.
/// @param completionHandler Receives which patterns were detected, or an error.
- (void)detectPatternsForPatterns:(NSSet<UIPasteboardDetectionPattern> *)patterns
completionHandler:(void(^)(NSSet<UIPasteboardDetectionPattern> * _Nullable,
NSError * _Nullable))completionHandler NS_REFINED_FOR_SWIFT API_AVAILABLE(ios(14.0));

/// Detects patterns in the specified pasteboard items.
///
/// @param patterns Detect only these patterns.
/// @param itemSet Specifies which pasteboard items by their position. Nil means all items.
/// @param completionHandler Receives which patterns were detected per item specified,
/// or an error.
- (void)detectPatternsForPatterns:(NSSet<UIPasteboardDetectionPattern> *)patterns
inItemSet:(NSIndexSet * _Nullable)itemSet
completionHandler:(void(^)(NSArray<NSSet<UIPasteboardDetectionPattern> *> * _Nullable,
NSError * _Nullable))completionHandler NS_REFINED_FOR_SWIFT API_AVAILABLE(ios(14.0));
  • 例子
NSSet *patterns = [[NSSet alloc] initWithObjects:UIPasteboardDetectionPatternProbableWebURL, nil];

[[UIPasteboard generalPasteboard] detectPatternsForPatterns:patterns completionHandler:^(NSSet<UIPasteboardDetectionPattern> * _Nullable result, NSError * _Nullable error) {
if (result && result.count) {
// 当前剪切板中存在 URL

1.2 使用changeCount来记录剪切板的数据是否发生变化


iOS小技能:iOS14 读取用户剪切板数据弹出提示的兼容方案_ios_04

记录一下真正读取剪切板时的​​changeCount​​,如果下次读取的时候没有发生变化则不读取。 这样一来效果就好多了,应用运行生命周期内,基本上只会弹出一次提示

II 、 查找哪些SDK使用了剪切板

app出现了从后台唤起会弹出 读取剪切板的 提示,安全部门要求要赶紧查,全局搜索了code,发现并没有读取剪切板的代码,比窦娥还冤,只能是第三方SDK的了,

2.1 Symbolic breakpoint 进行查找


  • 用Xcode的Symbolic breakpoint,调试​​[UIPasteboard generalPasteboard]​

iOS小技能:iOS14 读取用户剪切板数据弹出提示的兼容方案_剪切板_05


iOS小技能:iOS14 读取用户剪切板数据弹出提示的兼容方案_剪切板_06

使用例子:

  • 从后台唤起app会有这个提示
  • 单步向下走几步,然后就会出现调用方

iOS小技能:iOS14 读取用户剪切板数据弹出提示的兼容方案_剪切板_07

在这里插入图片描述

立马发现了JCore iOS SDK在iOS 14引用剪贴板该行为会导致APP被用户怀疑隐私泄露,请予以重视

升级新版进行适配 iOS 14。

'JPush' , '3.3.6'

2.2 使用命令行查找哪些SDK使用了剪切板

  • ​grep -r "UIPasteboard" .​
  • iOS小技能:iOS14 读取用户剪切板数据弹出提示的兼容方案_掘金·日新计划_08

➜  retail git:(develop) grep -r "UIPasteboard" .
./retail/other/tool/CopyTextLabel/QCTCopyTextLabel.m: UIPasteboard * paste = [UIPasteboard generalPasteboard];
./retail/class/business/Merchant_self_recording开户申请/oldNewAddStores/NewAddStores/QCTCopyLabel.m: UIPasteboard * paste = [UIPasteboard generalPasteboard];
./retail/class/business/Merchant_self_recording开户申请/oldNewAddStores/NewAddStores/QCTStoresDetailViewController.m: [UIPasteboard generalPasteboard].string = titleLab.text ? titleLab.text : @"";
Binary file ./Pods/JCore/libjcore-ios-2.3.2.a matches
./Pods/QMUIKit/QMUIKit/QMUIComponents/QMUILabel.m: UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
  • ​find . -type f | grep -e ".framework" | xargs grep -s UIPasteboard​
type f | grep -e ".framework"
  • ​find . -type f | grep -e ".a" | xargs grep -s AUPasteboard​

III 、例子:升级JPush SDK

'JPush' , '3.3.6'

iOS小技能:iOS14 读取用户剪切板数据弹出提示的兼容方案_掘金·日新计划_09

在这里插入图片描述

iOS小技能:iOS14 读取用户剪切板数据弹出提示的兼容方案_ios_10

在这里插入图片描述

IV、 see also

iOS小技能:iOS14 读取用户剪切板数据弹出提示的兼容方案_插入图片_11

在这里插入图片描述

4.1 升级CocoaPods(适配Xcode12)

  • 升级采用gem即可,命令如下
sudo gem install cocoapods

发现版本1.9.1 与Xcode12 不是很匹配,于是就升级新版本看下。

➜  Housekeeper git:(develop) pod --version
1.9.1

如果没升级,主要问题是,如果采用​​pod install --verbose --no-repo-update 之后,Xcode的编译设置​​不会 自动修改other Linker Flags

iOS小技能:iOS14 读取用户剪切板数据弹出提示的兼容方案_ios_12

在这里插入图片描述

iOS小技能:iOS14 读取用户剪切板数据弹出提示的兼容方案_ios_13

在这里插入图片描述

升级到1.9.3 再次升级SDK的时候,就适配Xcode12,可以自动修改other Linker Flags参数了

iOS小技能:iOS14 读取用户剪切板数据弹出提示的兼容方案_ios_14

在这里插入图片描述

因此升级Xcode的时候,最好也同时升级下CocoaPods