精通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。

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

UPDATED:

iOS7修改了UIPasteboard的部分设计。

这此之前,你只要知道任何一个UIPasteboard的Name,就能访问其中的内容,而现在,只有在同一CFBundleIdentifier标识下的App才能共享内容,如com.mycompany.a和com.mycompany.b,它们的com.mycompany部分是一样的,就能共享。

时间: 2024-12-22 02:54:51

精通UIPasteboard 粘贴板的相关文章

iOS中管理剪切板的UIPasteboard粘贴板类用法详解_IOS

一.自带剪切板操作的原生UI控件在iOS的UI系统中,有3个控件自带剪切板操作,分别是UITextField.UITextView与UIWebView.在这些控件的文字交互处进行长按手势可以在屏幕视图上唤出系统的剪切板控件,用户可以进行复制.粘贴,剪切等操作,其效果分别如下图所示. UITextField的文字操作 UITextView的文字操作 二.系统的剪切板管理类UIPasteboard 实际上,当用户通过上面的空间进行复制.剪切等操作时,被选中的内容会被存放到系统的剪切板中,并且这个剪切

Windows 8开发入门(十四) windows 8中粘贴板(剪切板)的使用

在Windows 8中我们的粘贴板分别保存4种信息:文本.图片.网页.文件.在本文中我们将分别复制和粘 贴这4种元素,当然你也可以在外部复制这4种元素,然后在程序中粘贴出来. DataPackage:包含用户 希望与另一个应用程序交换的数据 //设置一个中转变量保存用户的值 DataPackage dp = new DataPackage(); 第一:我们来看看复制和粘贴文本的后台处理代码 . //<!--复制文本--> private void CopyText_Click(object s

Win7系统笔记本电脑怎样清除粘贴板内容?

  Win7系统笔记本电脑怎样清除粘贴板内容? 1.在桌面上单击右键,选择"新建"-"快捷方式"; 2.在"请输入对象的位置"后面框中输入: cmd /c "echo off | clip" 点击下一步; 3.将键入该快捷方式的名称下面框中输入:清除剪切板(输入啥都可以,目的是为了让自己知道这个是什么)点击完成; 4.当我们复制了一些东西,如果不想要了,直接双击打开"清除剪切板"就可将复制的内容清除掉了.

js实现点击图片将图片地址复制到粘贴板的方法

 这篇文章主要介绍了js实现点击图片将图片地址复制到粘贴板的方法,涉及js操作节点的技巧,非常具有实用价值,需要的朋友可以参考下     本文实例讲述了js实现点击图片将图片地址复制到粘贴板的方法.分享给大家供大家参考.具体如下:   代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transition

wm-我想实现qq群发的功能,就是说把粘贴板上的内天发给好友,然后关闭好友对话框,求老司机指路

问题描述 我想实现qq群发的功能,就是说把粘贴板上的内天发给好友,然后关闭好友对话框,求老司机指路 // PostMsgDemo.cpp: 定义控制台应用程序的入口点 // #include"stdafx.h" #include BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM param) { char strClassName[MAXBYTE] = { 0 }; GetClassNameA(hWnd, strClassName, MAX

如何给 发送粘贴板-C#如何给QQ发送粘贴板?

问题描述 C#如何给QQ发送粘贴板? 目前只可以发文字,不知道如何发粘贴板? private bool SendQQMsg(IntPtr hWnd string qqcaption string sendtext) { try { NativeMethods.ShowWindow(hWnd NativeMethods.ShowWindowCommands.Normal); NativeMethods.BringWindowToTop(hWnd); SendKeys.SendWait(sendte

【UWP通用应用开发】集成搜索、粘贴板以及设置共享源和共享目标

在应用中集成搜索 上一节是关于如何添加应用设置和帮助,这一篇讲的是和设置类似的搜索. So-- Let's do it ! 先从简单的页面布局开始,想想我们需要什么,一个带搜索事件的Button,还需要一些TextBlock来提示用户,核心部分自然是一个GridView咯. <Grid Background="Wheat"> <Grid.RowDefinitions> <RowDefinition Height="Auto" />

js实现点击图片将图片地址复制到粘贴板的方法_javascript技巧

本文实例讲述了js实现点击图片将图片地址复制到粘贴板的方法.分享给大家供大家参考.具体如下: 复制代码 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml

qq-我想实现把粘贴板上的消息发给好友,然后关闭对话框,求大神帮忙

问题描述 我想实现把粘贴板上的消息发给好友,然后关闭对话框,求大神帮忙 // PostMsgDemo.cpp: 定义控制台应用程序的入口点// #include""stdafx.h""#includeBOOL CALLBACK EnumWindowsProc(HWND hWnd LPARAM param){ char strClassName[MAXBYTE] = { 0 };GetClassNameA(hWnd strClassName MAXBYTE);if (