最近看了苹果的UIPasteboard文档,看完之后写个blog记录下。
有些术语还是会用英文,翻译太烂失去原有的感觉。
UIPasteboard主要用途:
让app可以和其他app共享数据
1. 使用全系统范围粘贴板(system-wide pasteboards),可以和任意app共享数据
2. 使用app特定粘贴板(app-specific pasteboards),可以和相同team ID的app共享数据
一个粘贴板就是一个可用于分享数据的有名字标识内存区域。
系统粘贴板
有两种:全局粘贴板(the General pasteboard),查找粘贴板(the Find pasteboard)。其中查找粘贴板经验证无效,可以当它不存在了,文档写的挺好,可惜获取不到数据,服!
一个粘贴板必须有一个唯一的名字标识。粘贴板有个属性persistent,设置为YES,粘贴板会app终结和系统重启之后持续存在。系统粘贴板persistent默认是YES,app特定粘贴板默认是NO。
粘贴板的存储是以item的方式,一个item是一个或多个键值对。举个栗子:
UIPasteboard *pb = [UIPasteboard generalPasteboard];
pb.string = @"hello";
NSLog(@"%@", pb.items);
NSLog(@"%@", pb.string);
输出:
(
{
"public.utf8-plain-text" = hello;
}
)
hello
为什么这里这接使用pb.string,因为发现这个属性太方便了,常用的类型不用再繁琐,目前这种属性提供以下几种:string,URL,image,color,以及对应的数组strings,URLs,images,colors。我觉得简单的数据共享用这种足够了。
存储和读取
1. pasteboard type
一般用来存储/读取的数据类型pasteboard type是“Uniform Type Identifier (UTI) ”,这个东西是苹果为了统一文件/数据等类型而定义的。一个UTI用来唯一标识一种类型。比较难理解,可以举个栗子:
一个文本文件,后缀可能是:txt、text等。另外一个应用可以打开.txt文件可能也能打开.html文件。一个应用检测所有可以读取的文件类型是不可能的,用户体验就变得很糟糕,用户不理解为什么app可以打开一个文本却不能打开另外一个。所以苹果为了解决这个问题就定义了UTI。翻译的少了好多意味,有兴趣直接去看原文Uniform Type Identifiers Overview
不喜欢这个东西,感觉苹果这块做的不好。要在程序中使用UTI,可以直接查找对应的列表找到合适的字符串直接使用,但是,这种方式我是不能接受的,理由不谈了。后来发现是有对应的常量,定义在UTCoreTypes.h中。要使用常量要走三步,
1、引入MobileCoreServices.framework
2、#import <MobileCoreServices/UTCoreTypes.h>
3、转换为NSString,(NSString *)kUTTypePlainText
至于为什么要有第三步,因为UIPasteboard的函数中需要type都是NSString类型的。
2. 函数
2.1 粘贴板获取和删除
+ (UIPasteboard *)generalPasteboard
获取系统全局粘贴板,也就是说名叫UIPasteboardNameGeneral的系统粘贴板
+ (UIPasteboard *)pasteboardWithName:(NSString *)pasteboardName create:(BOOL)create
获取对应pasteboardName的粘贴板,create=YES表示如果没有则创建。
+ (UIPasteboard *)pasteboardWithUniqueName
获取一个有唯一名字的app粘贴板。
+ (void)removePasteboardWithName:(NSString *)pasteboardName
删除一个粘贴板
2.2 Object类型数据读写(单个item)
比如: NSString, NSArray, NSDictionary, NSDate, NSNumber, UIImage, NSURL
- (void)setValue:(id)value forPasteboardType:(NSString *)pasteboardType
- (id)valueForPasteboardType:(NSString *)pasteboardType
pasteboardType就是对应数据的UTI。如果pasteboardType和value不匹配,粘贴板不会进行赋值,它什么也不干。
2.3 二进制数据或者自定义pasteboardType(单个item)
- (void)setData:(NSData *)data forPasteboardType:(NSString *)pasteboardType
- (NSData *)dataForPasteboardType:(NSString *)pasteboardType
pasteType可以是UTI,也可以自己定义的pasteboardType。自定义pasteboardType一般的命名方式是com.companyName.packageName.typeName。
举个栗子:
#define PASTE_BOARD_NAME @"com.dali.pasteboard"
#define PASTE_BOARD_TYPE @"com.dali.pasteboard.dictionary"
-(void) writeDictToPasteBoard:(NSDictionary*) dict
{
// 获取一个pasteboard,如果没有创建
UIPasteboard * pb = [UIPasteboard pasteboardWithName:PASTE_BOARD_NAME create:YES];
// 使pasteboard可持久
[pb setPersistent:TRUE];
// 将dict变为NSData并,存储进粘贴板
[pb setData:[NSKeyedArchiver archivedDataWithRootObject:dict] forPasteboardType:PASTE_BOARD_TYPE];
}
-(NSDictionary*) readDictFromPasteboard
{
UIPasteboard * pb=[UIPasteboard pasteboardWithName:PASTE_BOARD_NAME create:NO];
NSData * data=[pb valueForPasteboardType:PASTE_BOARD_TYPE];
NSDictionary * dict;
if (!data) {
return nil;
}
@try {
dict = [NSKeyedUnarchiver unarchiveObjectWithData:data];
}
@catch (NSException* exception)
{
NSLog(@"Exception: %@",exception);
return nil;
}
return dict;
}
2.4. 其他的一些函数,比如多个item操作,判断类型之类的,我用的不多,如果详细看,请看 Apple文档
文章内容参考了:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIPasteboard_Class
http://hayageek.com/uipasteboard-example-read-write-share/