iOS 精通UIPasteboard 粘贴板

有时候我们可能需要复制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:)); 

//针对于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]; 
    UIMenuController *menu = [UIMenuController sharedMenuController]; 
    [menu setTargetRect:self.frame inView:self.superview]; 
    [menu setMenuVisible:YES animated: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,粘贴到地址栏去,而我们可以在应用程序间“悄悄”的通信、共享数据。


注:这里的“悄悄”只是说其他的应用程序不知道,而系统是允许的。
 


我们用模板Single View Application来创建两个简单的工程,一个叫PasteBoardWrite,另一个叫PasteBoardRead,界面分别如下:

    \     \
 


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

用自己创建的粘贴板,能只在你的本地应用之间通信,有时候它能让你的用户体验变得更好,比如微信就是这么做的。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值