iOS16適配之剪貼板

背景

Apple從iOS14后,增加了對剪貼板內(nèi)容的隱私保護


131217723881.jpeg

iOS16的剪貼板彈窗。


936be07d1526176.jpg

問題

雖然用戶的隱私被更好的保護了,但用戶體驗也在下降。
在iOS16中,只要讀取了[UIPasteboard generalPasteboard].string
就會彈出是否允許的彈窗,且彈窗沒有暴露api來控制,也沒有記錄上次的點擊結(jié)果。如果拒絕,下次讀取還是會彈出。

解決方案

針對剪貼版的問題。有兩種解決方案

1.用戶主動讀取剪貼板

使用iOS16 UIKit的新組件 UIPasteControl,來讀取剪貼板內(nèi)容,則不會觸發(fā)彈窗

用法

  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方法,用于監(jiān)聽pasteControl點擊后的回調(diào)

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

2.用戶無感知讀取

如淘寶分享商品,雖然不能避免觸發(fā)讀取剪貼板的彈窗,但可以利用一些不會觸發(fā)彈窗的,判斷內(nèi)容的api。來減少彈窗出現(xiàn)的概率,增大讀取準確內(nèi)容的命中率。

用法

使用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<UIPasteboardDetectionPattern> * _Nullable set, NSError * _Nullable error) {
        
        for (NSString *type in set) {
            if ([type isEqualToString:UIPasteboardDetectionPatternProbableWebURL]) {
                //do something
            }
        }
    }];

總結(jié)

Apple一直是一家重視用戶隱私的企業(yè),但這次iOS16關(guān)于剪貼板的更新,蘋果自己的設(shè)計師也覺得有些過量,目前的解決方案也是盡量提高下用戶體驗。下個版本iOS16.1不知道是否有更優(yōu)雅的解決方式。后續(xù)如果有需要也可以更新一下swift的實現(xiàn)。大家有更好的方案也可以一起討論。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內(nèi)容