在iOS中下面三个控件,自身就有复制-粘贴的功能:数组
一、UITextViewapp
二、UITextFieldui
三、UIWebViewurl
UIKit framework提供了几个类和协议方便咱们在本身的应用程序中实现剪贴板的功能。spa
一、UIPasteboard:咱们能够向其中写入数据,也能够读取数据
二、UIMenuController:显示一个快捷菜单,用来展现复制、剪贴、粘贴等选择的项。
三、UIResponder中的 canPerformAction:withSender:用于控制哪些命令显示在快捷菜单中。
四、当快捷菜单上的命令点击的时候,UIResponderStandardEditActions将会被调用。
下面这些项能被放置到剪贴板中
一、UIPasteboardTypeListString — 字符串数组, 包含kUTTypeUTF8PlainText
二、UIPasteboardTypeListURL — URL数组,包含kUTTypeURL
三、UIPasteboardTypeListImage — 图形数组, 包含kUTTypePNG 和kUTTypeJPEG
四、UIPasteboardTypeListColor — 颜色数组
剪贴板的类型分为两种:
系统级:使用UIPasteboardNameGeneral和UIPasteboardNameFind,系统级应用程序关闭,或者卸载的数据不会丢失。code
应用程序级:经过设置,可让数据在应用程序关闭以后仍然保存在剪贴板中,可是应用程序卸载以后数据就会失去。咱们可用经过pasteboardWithName:create:来建立。orm
例子以下:继承
有时候咱们可能须要复制UILabel上的文本,或者UIImageView的图片,而UILabel和UIImageView默认是不响应Touch事件的,也没法复制,那么咱们就须要本身实现一个可复制的UILabel。新添加一个类继承自UILabel:事件
@interface UICopyLabel : UILabel @end #import "UICopyLabel.h" @implementation UICopyLabel @end
为了能接收到事件(能成为第一响应者),咱们须要覆盖一个方法:图片
-(BOOL)canBecomeFirstResponder { return YES; }
还须要针对复制的操做覆盖两个方法:
// 能够响应的方法 -(BOOL)canPerformAction:(SEL)action withSender:(id)sender { return (action == @selector(copy:)); }
//针对于响应方法的实现 -(void)copy:(id)sender { UIPasteboard *pboard = [UIPasteboard generalPasteboard]; pboard.string = self.text; }
有了以上三个方法,咱们就能处理copy了,固然,在能接收到事件的状况下:
//UILabel默认是不接收事件的,咱们须要本身添加touch事件 -(void)attachTapHandler { self.userInteractionEnabled = YES; //用户交互的总开关 UITapGestureRecognizer *touch = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)]; touch.numberOfTapsRequired = 2; [self addGestureRecognizer:touch]; [touch release]; } //绑定事件 - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self attachTapHandler]; } return self; } //同上 -(void)awakeFromNib { [super awakeFromNib]; [self attachTapHandler]; }
咱们已经能够接收到事件了!因为我在上方将tap数设为2,因此须要双击才能捕获,接下来,咱们须要处理这个tap,以便让菜单栏弹出来:
-(void)handleTap:(UIGestureRecognizer*) recognizer { [self becomeFirstResponder]; UIMenuItem *copyLink = [[[UIMenuItemalloc] initWithTitle:@"复制" action:@selector(copy:)]autorelease]; [[UIMenuControllersharedMenuController] setMenuItems:[NSArrayarrayWithObjects:copyLink, nil]]; [[UIMenuControllersharedMenuController] setTargetRect:self.frameinView:self.superview]; [[UIMenuControllersharedMenuController] setMenuVisible:YESanimated: YES]; }
这样一来,一个可复制的UILabel就诞生了!它能处理接收点击、弹出菜单栏、处理copy,这是一个很普通的可复制控件。
接下来咱们作一个可复制的UIImageView,建立一个新的viewController,放两个imageView,默认显示不一样的图:
而后把上面的代码直接拷过来,改三个地方:
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender { return (action == @selector(copy:) || action == @selector(paste:)); } -(void)copy:(id)sender { UIPasteboard *pboard = [UIPasteboard generalPasteboard]; pboard.image = self.image; } -(void)paste:(id)sender { UIPasteboard *pboard = [UIPasteboard generalPasteboard]; self.image = pboard.image; }
UIPasteboard有系统级别和应用级别两种类型,因此不只能够在应用程序内通讯,还能在应用程序间通讯,好比我复制一个url,而后打开safari,粘贴到地址栏去,而咱们能够在应用程序间通讯、共享数据。
在PasteBoardWrite里面点“写入”后把textField中的文本写入粘贴板,而后切换到PasteBoardRead的时候显示出来。若是咱们的粘贴板只想给“本身人”用的话,就不能用系统的通用粘贴板,须要咱们本身建立一个:
//须要提供一个惟一的名字,通常使用倒写的域名:com.mycompany.myapp.pboard //后面的参数表示,若是不存在,是否建立一个 UIPasteboard *pb = [UIPasteboard pasteboardWithName:@"testBoard" create:YES];
使用这个粘贴板,咱们能够把文本存进去,而后在另外一个app里面读出来,一些经常使用的类型已经被设置为属性了:
除此以外,若是是可以转换成plist的数据类型(NSString, NSArray, NSDictionary, NSDate, NSNumber 和 NSURL),咱们能够调用setValue:forPasteboardType:方法去存储数据,其余类型只能调用setData:forPasteboardType:方法(plist数据类型也可以使用),相似于这样:
//存储数据 NSDictionary *dict = [NSDictionary dictionaryWithObject:textField.text forKey:@"content"]; NSData *dictData = [NSKeyedArchiver archivedDataWithRootObject:dict]; [pb setData:dictData forPasteboardType:@"myType"]; //获取就相似于这样: UIPasteboard *pb = [UIPasteboard pasteboardWithName:@"testBoard" create:YES]; NSDictionary *dict = [NSKeyedUnarchiver unarchiveObjectWithData:[pb dataForPasteboardType:@"myType"]]; caption.text = [dict objectForKey:@"content"];
上面提到了一个PasteboardType,这是一个统一类型标识符(Uniform Type Identifier UTI),能帮助app获取本身能处理的数据。好比你只能处理文本的粘贴,那给你一个UIImage显然是无用的。你可使用公用的UTI,也可使用任意字符,苹果建议使用倒写的域名加上类型名:com.myCompany.myApp.myType。