iOS16适配之剪贴板

背景

Apple从iOS14后,增加了对剪贴板内容的隐私保护


131217723881.jpeg

iOS16的剪贴板弹窗。


936be07d1526176.jpg

问题

虽然用户的隐私被更好的保护了,但用户体验也在下降。
在iOS16中,只要读取了[UIPasteboard generalPasteboard].string
就会弹出是否允许的弹窗,且弹窗没有暴露api来控制,也没有记录上次的点击结果。如果拒绝,下次读取还是会弹出。

解决方案

针对剪贴版的问题。有两种解决方案

1.用户主动读取剪贴板

使用iOS16 UIKit的新组件 UIPasteControl,来读取剪贴板内容,则不会触发弹窗

用法

  1. 初始化pasteControl

@interface ViewController ()

@property (nonatomic, strong) UIPasteControl *pasteControl;

@end

@implementation ViewController

- (void)viewDidLoad {
    self.control = [[TestPasteControl alloc] init];
    self.control.target = self;
    
    [self.view addSubview:self.control];
    self.control.frame = CGRectMake(0, 0, 100, 100);
}
  1. 配置configuration(支持类型)
- (void)viewDidLoad {
    // ...
    self.pasteConfiguration = [[UIPasteConfiguration alloc] initWithTypeIdentifiersForAcceptingClass:[NSString class]];
}

3.target重写pasteItemProviders:itemProviders方法,用于监听pasteControl点击后的回调

- (void)pasteItemProviders:(NSArray *)itemProviders {
    for (NSItemProvider *provider in itemProviders) {
        [provider loadObjectOfClass:NSString.class
              completionHandler:^(id  _Nullable object, NSError * _Nullable error) {
            if (object) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    NSString *result = [NSString stringWithFormat:@"复制的内容: %@", object];
                    NSLog(@"%@",result);
                });
            }
        }];
    }
}

2.用户无感知读取

如淘宝分享商品,虽然不能避免触发读取剪贴板的弹窗,但可以利用一些不会触发弹窗的,判断内容的api。来减少弹窗出现的概率,增大读取准确内容的命中率。

用法

使用iOS14新增的api

detectPatternsForPatterns:completionHandler:
detectPatternsForPatterns:inItemSet:completionHandler: 

来提前判断

可以判断的类型

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));

/// Array of DDMatchLink values
UIKIT_EXTERN UIPasteboardDetectionPattern const UIPasteboardDetectionPatternLink NS_REFINED_FOR_SWIFT API_AVAILABLE(ios(15.0));
/// Array of DDMatchPhoneNumber values
UIKIT_EXTERN UIPasteboardDetectionPattern const UIPasteboardDetectionPatternPhoneNumber NS_REFINED_FOR_SWIFT API_AVAILABLE(ios(15.0));
/// Array of DDMatchEmailAddress values
UIKIT_EXTERN UIPasteboardDetectionPattern const UIPasteboardDetectionPatternEmailAddress NS_REFINED_FOR_SWIFT API_AVAILABLE(ios(15.0));
/// Array of DDMatchAddress values
UIKIT_EXTERN UIPasteboardDetectionPattern const UIPasteboardDetectionPatternPostalAddress NS_REFINED_FOR_SWIFT API_AVAILABLE(ios(15.0));
/// Array of DDMatchCalendarEvent values
UIKIT_EXTERN UIPasteboardDetectionPattern const UIPasteboardDetectionPatternCalendarEvent NS_REFINED_FOR_SWIFT API_AVAILABLE(ios(15.0));
/// Array of DDMatchShipmentTrackingNumber values
UIKIT_EXTERN UIPasteboardDetectionPattern const UIPasteboardDetectionPatternShipmentTrackingNumber NS_REFINED_FOR_SWIFT API_AVAILABLE(ios(15.0));
/// Array of DDMatchFlightNumber values
UIKIT_EXTERN UIPasteboardDetectionPattern const UIPasteboardDetectionPatternFlightNumber NS_REFINED_FOR_SWIFT API_AVAILABLE(ios(15.0));
/// Array of DDMatchMoneyAmount values
UIKIT_EXTERN UIPasteboardDetectionPattern const UIPasteboardDetectionPatternMoneyAmount  NS_REFINED_FOR_SWIFT API_AVAILABLE(ios(15.0));

判断逻辑

    UIPasteboard *board = [UIPasteboard generalPasteboard];
    [board detectPatternsForPatterns:[NSSet setWithObjects:UIPasteboardDetectionPatternProbableWebURL, UIPasteboardDetectionPatternNumber, UIPasteboardDetectionPatternProbableWebSearch, nil]
                   completionHandler:^(NSSet * _Nullable set, NSError * _Nullable error) {
        
        for (NSString *type in set) {
            if ([type isEqualToString:UIPasteboardDetectionPatternProbableWebURL]) {
                //do something
            }
        }
    }];

总结

Apple一直是一家重视用户隐私的企业,但这次iOS16关于剪贴板的更新,苹果自己的设计师也觉得有些过量,目前的解决方案也是尽量提高下用户体验。下个版本iOS16.1不知道是否有更优雅的解决方式。后续如果有需要也可以更新一下swift的实现。大家有更好的方案也可以一起讨论。

你可能感兴趣的:(iOS16适配之剪贴板)