在iOS中下面三個控件啰扛,自身就有復(fù)制-粘貼的功能:
1妖谴、UITextView
2谜喊、UITextField
3枢赔、UIWebView
UIKit framework提供了幾個類和協(xié)議方便我們在自己的應(yīng)用程序中實現(xiàn)剪貼板的功能。
1括授、UIPasteboard:我們可以向其中寫入數(shù)據(jù)坞笙,也可以讀取數(shù)據(jù)
2、UIMenuController:顯示一個快捷菜單荚虚,用來展示復(fù)制薛夜、剪貼、粘貼等選擇的項版述。
3梯澜、UIResponder中的 canPerformAction:withSender:用于控制哪些命令顯示在快捷菜單中。
4渴析、當(dāng)快捷菜單上的命令點擊的時候晚伙,UIResponderStandardEditActions將會被調(diào)用。
下面這些項能被放置到剪貼板中
1俭茧、UIPasteboardTypeListString —? 字符串?dāng)?shù)組, 包含kUTTypeUTF8PlainText
2咆疗、UIPasteboardTypeListURL —? URL數(shù)組,包含kUTTypeURL
3母债、UIPasteboardTypeListImage —? 圖形數(shù)組, 包含kUTTypePNG 和kUTTypeJPEG
4民傻、UIPasteboardTypeListColor —? 顏色數(shù)組
剪貼板的類型分為兩種:
系統(tǒng)級:使用UIPasteboardNameGeneral和UIPasteboardNameFind,系統(tǒng)級應(yīng)用程序關(guān)閉场斑,或者卸載的數(shù)據(jù)不會丟失漓踢。
應(yīng)用程序級:通過設(shè)置,可以讓數(shù)據(jù)在應(yīng)用程序關(guān)閉之后仍然保存在剪貼板中漏隐,但是應(yīng)用程序卸載之后數(shù)據(jù)就會失去喧半。我們可用通過pasteboardWithName:create:來創(chuàng)建。
UILabel
例子如下:
有時候我們可能需要復(fù)制UILabel上的文本青责,或者UIImageView的圖片挺据,而UILabel和UIImageView默認是不響應(yīng)Touch事件的,也無法復(fù)制脖隶,那么我們就需要自己實現(xiàn)一個可復(fù)制的UILabel扁耐。
新添加一個類繼承自UILabel:
@interface UICopyLabel : UILabel
@end
#import "UICopyLabel.h"
@implementation UICopyLabel
@end
為了能接收到事件(能成為第一響應(yīng)者),我們需要覆蓋一個方法:
-(BOOL)canBecomeFirstResponder
{
return YES;
}
還需要針對復(fù)制的操作覆蓋兩個方法:
// 可以響應(yīng)的方法
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
return (action == @selector(copy:));
}
//針對于響應(yīng)方法的實現(xiàn)
-(void)copy:(id)sender
{
UIPasteboard *pboard = [UIPasteboard generalPasteboard];
pboard.string = self.text;
}
有了以上三個方法产阱,我們就能處理copy了婉称,當(dāng)然,在能接收到事件的情況下:
//UILabel默認是不接收事件的,我們需要自己添加touch事件
-(void)attachTapHandler
{
self.userInteractionEnabled = YES;? //用戶交互的總開關(guān)
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];
}
我們已經(jīng)可以接收到事件了王暗!由于我在上方將tap數(shù)設(shè)為2悔据,所以需要雙擊才能捕獲,
接下來俗壹,我們需要處理這個tap科汗,以便讓菜單欄彈出來:
-(void)handleTap:(UIGestureRecognizer*) recognizer
{
[self becomeFirstResponder];
UIMenuItem *copyLink = [[[UIMenuItemalloc] initWithTitle:@"復(fù)制"
action:@selector(copy:)]autorelease];
[[UIMenuControllersharedMenuController] setMenuItems:[NSArrayarrayWithObjects:copyLink, nil]];
[[UIMenuControllersharedMenuController] setTargetRect:self.frameinView:self.superview];
[[UIMenuControllersharedMenuController] setMenuVisible:YESanimated: YES];
}
這樣一來,一個可復(fù)制的UILabel就誕生了绷雏!它能處理接收點擊头滔、彈出菜單欄、處理copy涎显,這是一個很普通的可復(fù)制控件坤检。
UIImageView
接下來我們做一個可復(fù)制的UIImageView,創(chuàng)建一個新的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有系統(tǒng)級別和應(yīng)用級別兩種類型膘婶,所以不僅可以在應(yīng)用程序內(nèi)通信,還能在應(yīng)用程序間通信蛀醉,比如我復(fù)制一個url悬襟,然后打開safari,粘貼到地址欄去拯刁,而我們可以在應(yīng)用程序間通信脊岳、共享數(shù)據(jù)。
在PasteBoardWrite里面點“寫入”后把textField中的文本寫入粘貼板垛玻,然后切換到PasteBoardRead的時候顯示出來割捅。如果我們的粘貼板只想給“自己人”用的話,就不能用系統(tǒng)的通用粘貼板帚桩,需要我們自己創(chuàng)建一個:
//需要提供一個唯一的名字亿驾,一般使用倒寫的域名:com.mycompany.myapp.pboard
//后面的參數(shù)表示,如果不存在账嚎,是否創(chuàng)建一個
UIPasteboard *pb = [UIPasteboard pasteboardWithName:@"testBoard" create:YES];
使用這個粘貼板莫瞬,我們可以把文本存進去,然后在另一個app里面讀出來郭蕉,一些常用的類型已經(jīng)被設(shè)置為屬性了:
除此之外疼邀,如果是能夠轉(zhuǎn)換成plist的數(shù)據(jù)類型(NSString, NSArray, NSDictionary, NSDate, NSNumber 和 NSURL),我們可以調(diào)用setValue:forPasteboardType:方法去存儲數(shù)據(jù)召锈,其他類型只能調(diào)用setData:forPasteboardType:方法(plist數(shù)據(jù)類型也可使用)旁振,類似于這樣:
//存儲數(shù)據(jù)
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, 這是一個統(tǒng)一類型標識符(Uniform Type Identifier? UTI),能幫助app獲取自己能處理的數(shù)據(jù)。比如你只能處理文本的粘貼规求,那給你一個UIImage顯然是無用的筐付。你可以使用公用的UTI,也可以使用 任意字符阻肿,蘋果建議使用倒寫的域名加上類型名:com.myCompany.myApp.myType瓦戚。