尽管“hasStrings”为真,UIPasteBoard“string”属性返回nil

问题描述

我有以下代码用于抓取用户从应用程序外部复制到剪贴板的文本,以便他们可以将其粘贴到应用程序中:

UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];

if ([pasteboard hasstrings])
{
    Nsstring *text = pasteboard.string;
}

这一直很有效,直到 iOS14 我注意到我一直在崩溃,因为 pasteboard.stringnil,尽管 hasstrings 是真的。

我查看了文档,发现确实,pasteboard.string 可能是 nil

存储在这属性中的值是一个 Nsstring 对象。这 表示类型的关联数组是 UIPasteboardTypeListString,包括类型 kUTTypeUTF8PlainText。 设置此属性会替换粘贴板中的所有当前项目 与新项目。如果第一项没有指定的值 类型,返回 nil。

我的意思是剪贴板中有某种不是 kUTTypeUTF8PlainText 的字符串,这就是为什么 pasteboard.stringnil,但这是正确的解释吗?

我只是对这里到底发生了什么感到困惑,如果遇到 pasteboard.stringnil 的情况,我不确定要告诉我的用户什么?

解决方法

-[UIPasteboard hasStrings] == YES 仅表示粘贴板中的项目具有 public.utf8-plain-text 类型或任何其他表明它是字符串的类型。

但是,如果 -[UIPasteboard string] 类的对象不能从 nil 提供的任何数据构造出来,NSString 仍然可以返回 itemProviders

以下是重现您所处情况的示例:

首先实现一个符合NSItemProviderWriting的测试类

#import <Foundation/Foundation.h>

static NSString *const UTTypeUTF8PlainText = @"public.utf8-plain-text";

@interface TestObject : NSObject <NSItemProviderWriting>

@end

@implementation TestObject

- (NSData *)randomDataWithLength:(NSUInteger)length {
    NSMutableData *data = [NSMutableData dataWithLength:length];
    SecRandomCopyBytes(kSecRandomDefault,length,data.mutableBytes);
    return data;
}

#pragma mark - NSItemProviderWriting

+ (NSArray<NSString *> *)writableTypeIdentifiersForItemProvider {
    return @[UTTypeUTF8PlainText];
}

- (nullable NSProgress *)loadDataWithTypeIdentifier:(nonnull NSString *)typeIdentifier forItemProviderCompletionHandler:(nonnull void (^)(NSData * _Nullable,NSError * _Nullable))completionHandler {
    // random data that an utf8 string may not be constructed from
    NSData *randomData = [self randomDataWithLength:1];
    completionHandler(randomData,nil);
    return nil;
}

@end

然后将测试对象放入粘贴板

if (@available(iOS 11.0,*)) {
    UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
    TestObject *item = [TestObject new];
    [pasteboard setObjects:@[item]];
    
    if ([pasteboard hasStrings]) {
        // text may be nil
        NSString *text = pasteboard.string;
    }
}