在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。