iOS开发应用中的剪贴板功能教程:
本文将介绍如何在iOS中使用剪贴板实现应用程序之间的数据共享。例如,您可以从iPhone QQ复制一个URL,然后将其粘贴到Safari浏览器中查看该链接的内容。
一、在iOS中,有三个控件自带复制-粘贴功能:
1. UITextView
2. UITextField
3. UIWebView
二、UIKit框架提供了几个类和协议,方便我们在自己的应用程序中实现剪贴板功能。
1. UIPasteboard:我们可以向其中写入数据,也可以读取数据。
2. UIMenuController:显示一个快捷菜单,用于复制、剪贴、粘贴选择的项。
3. UIResponder中的canPerformAction:withSender:方法,用于控制哪些命令显示在快捷菜单中。
4. 当快捷菜单上的命令被点击时,UIResponderStandardEditActions将被调用。
三、以下内容可以放置到剪贴板中:
1. UIPasteboardTypeListString:字符串数组,包含kUTTypeUTF8PlainText。
2. UIPasteboardTypeListURL:URL数组,包含kUTTypeURL。
3. UIPasteboardTypeListImage:图形数组,包含kUTTypePNG和kUTTypeJPEG。
4. UIPasteboardTypeListColor:颜色数组。
四、剪贴板的类型分为两种:
1. 系统级剪贴板:使用UIPasteboardNameGeneral和UIPasteboardNameFind创建。当应用程序关闭或卸载时,系统级剪贴板中的数据不会丢失。
2. 应用程序级剪贴板:通过设置,可以让数据在应用程序关闭后仍然保存在剪贴板中,但在应用程序卸载后,数据将丢失。可以使用pasteboardWithName:create:方法来创建应用程序级剪贴板。
了解这些概念后,我们将通过一些示例来说明如何在应用程序中使用剪贴板。
示例1:复制并粘贴文本。
在tableview上显示一个快捷菜单,上面只有复制按钮。从tableview上复制文本后,将其粘贴到标题栏上。
```objc
// 定义一个单元格类CopyTableViewCell
#import "CopyTableViewCell.h"
@interface CopyTableViewCell : UITableViewCell
{
id delegate; // 代理
}
@property (nonatomic, retain) id delegate; // 代理属性
@end
// 实现CopyTableViewCell
#import "CopyTableViewCell.h"
@implementation CopyTableViewCell
@synthesize delegate; // 初始化方法中设置代理属性
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) { }
return self;
}
// 设置选中状态和高亮状态时调用的方法,显示快捷菜单并设置高亮效果
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
}
- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated {
[[self delegate] performSelector:@selector(showMenu:) withObject:self afterDelay:0.9f]; // 显示快捷菜单动画延时0.9秒
[super setHighlighted:highlighted animated:animated]; // 设置高亮效果
}
// 可响应键盘事件的方法,返回YES表示可以成为第一响应者,可以执行copy操作,返回NO则不可执行copy操作
- (BOOL)canBecomeFirstResponder {
return YES;
}
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender{
if (action == @selector(cut:)){ // 如果操作为复制操作,返回NO表示不可执行该操作
return NO;
} else if(action == @selector(copy:)){ // 如果是copy操作,返回YES表示可以执行该操作
return YES;
} else{ // 其他操作返回NO表示不可执行
return NO;
}
}
```
```objc
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
if ([action isEqualToString:@selector(paste:)]) {
return NO;
} else if ([action isEqualToString:@selector(select:)]) {
return NO;
} else if ([action isEqualToString:@selector(selectAll:)]) {
return NO;
} else {
return [super canPerformAction:action withSender:sender];
}
}
- (void)copy:(id)sender {
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
[pasteboard setString:[[self textLabel]text]];
}
- (void)dealloc {
[super dealloc];
}
```
定义CopyPasteTextController,实现粘贴功能。
```objc
@interface CopyPasteTextController : UIViewController
{
//用来标识是否显示快捷菜单
BOOL menuVisible;
UITableView *tableView;
}
@property (nonatomic, getter=isMenuVisible) BOOL menuVisible;
@property (nonatomic, retain) IBOutlet UITableView *tableView;
@end
```
实现CopyPasteTextController。
```objc
#import "CopyPasteTextController.h"
#import "CopyTableViewCell.h"
@implementation CopyPasteTextController
@synthesize menuVisible,tableView;
- (void)viewDidLoad {
[super viewDidLoad];
}
```
将提供的代码重构如下:
```objc
- (void)configureUI {
[self setTitle:@"文字复制粘贴"]; // 点击这个按钮将剪贴板的内容粘贴到title上
UIBarButtonItem *addButton = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(readFromPasteboard:)] autorelease];
[[self navigationItem] setRightBarButtonItem:addButton];
}
// 自定义表格视图中的分区数量。
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
// 自定义表格视图单元格的外观。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
CopyTableViewCell *cell = (CopyTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[CopyTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// 在此处可以自定义单元格的属性和内容,例如设置标题、文本等。
return cell;
}
```
在给定的内容中,我们可以重构以下方法和代码:
```objc
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
if([self isMenuVisible]) {
return nil;
}
NSString *text = [NSString stringWithFormat:@"Row %d", [indexPath row]];
UITableViewCell *cell = [[[self tableView] dequeueReusableCellWithIdentifier:@"CustomCellIdentifier"] autorelease];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"CustomCellIdentifier"];
}
cell.textLabel.text = text;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
[cell setDelegate:self];
[cell setSelected:YES animated:YES];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
[[cell textLabel] setText:[NSString stringWithFormat:@"Row %d", [indexPath row]]];
}
- (void)showMenu:(id)cell {
if ([cell isHighlighted]) {
[cell becomeFirstResponder];
UIMenuController * menu = [UIMenuController sharedMenuController];
[menu setTargetRect:[cell frame] inView:[self view]];
[menu setMenuVisible:YES animated:YES];
}
}
```
请根据提供的内容完成内容重构,并保持段落结构:
```
// Relinquish ownership any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload{
[super viewDidUnload];
[self.tableView release];
// Relinquish ownership of anything that can be recreated in viewDidLoad or on demand.
// For example: self.myOutlet = nil;
}
复制一行数据:
点击右上角的按钮粘贴,将数据显示在title上:
#p#
2、图片复制粘贴
下面通过一个例子,将图片复制和剪贴到另外一个UIImageView中间。
1、在界面上放置两个uiimageview,一个是图片的数据源,一个是将图片粘贴到的地方。CopyPasteImageViewController 代码如下:
@interface CopyPasteImageViewController : UIViewController {
UIImageView *imageView;
UIImageView *pasteView;
UIImageView *selectedView;
}
@property (nonatomic, retain) IBOutlet UIImageView *imageView;
@property (nonatomic, retain) IBOutlet UIImageView *pasteView;
@property (nonatomic, retain) UIImageView *selectedView;
- (void)placeImageOnPasteboard:(id)view;
@end
2、当触摸图片的时候我们显示快捷菜单:
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
NSSet *copyTouches = [event touchesForView:imageView];
```
重构后的代码如下:
```objc
NSSet *copyTouches = [event touchesForView:imageView];
NSSet *pasteTouches = [event touchesForView:pasteView];
[self becomeFirstResponder];
if ([copyTouches count] > 0) {
[self performSelector:@selector(showMenu:) withObject:imageView afterDelay:0.9f];
} else if ([pasteTouches count] > 0) {
[self performSelector:@selector(showMenu:) withObject:pasteView afterDelay:0.9f];
}
[super touchesBegan:touches withEvent:event];
}
- (void)showMenu:(id)view {
[self setSelectedView:view];
UIMenuController *menu = [UIMenuController sharedMenuController];
[menu setTargetRect: CGRectMake(5, 10, 1, 1) inView: view];
[menu setMenuVisible: YES animated: YES];
}
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender{
if (action == @selector(cut:)) {
return ([self selectedView] == imageView);
} else if (action == @selector(copy:)) {
return ([self selectedView] == imageView);
} else if (action == @selector(paste:)) {
return ([self selectedView] == pasteView);
} else if (action == @selector(selectAll:)) {
[[textField text] selectAll:YES];
return YES;
} else if (action == @selector(deletePreviousCharsFromSelection:)){
[[textField text] deletePreviousCharsFromSelection:YES];
return YES;
} else if (action == @selector(setSelectedTextRange:)){
NSRange range;
SEL cmd = action;
if (cmd == @selector(setSelectedTextRange:)){
range = sender; // this is the new NSRange that has been passed into us!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ^^^^^^^^^^^^^^^^^^^^^^^^^^^ THIS IS THE ONLY PART YOU'LL REALLY NEED TO KNOW :) it is the one and only parameter that you will need to know to call the setTextRange method and have it do whatever you want it to do so, all you really need to do is change the value of range to be whatever value you want, then call the method as normal and you're done. it will work perfectly. You can also do other stuff to it too... you can make it larger than it already is by using something like: range = NSMakeRange(someValue, someOtherValue)... or you can make it smaller by doing something like this: range = NSMakeRange(oldValue, newValue)... or you can change its location entirely by doing something like this: range = NSMakeRange(someNewLocation, someValue); you can even change both values at once by doing something like this: range = NSMakeRange(newLocation, newSize); you can change all of them at once, or any combination of them, by just changing the values above. you can also use a different variable name if you want, or even a totally different function call altogether... you have complete freedom here. it's up to you how you want to use it. it's up to you how to call it. it's up to you what you want it to do. so, again, all you really need to know is the single parameter -- that is, the range that has been sent into your function from outside of your code. so, don't worry about trying to understand every little detail of what's going on here. just focus on the part that you really need to know, which is the one and only parameter that you will need to pass into the setTextRange method to get your desired result. it doesn't matter how many times you call this function or how many different ways you use it, as long as you always use the same single parameter in order for it to work correctly. it doesn't matter what variables or functions are called inside of this function -- as long as they all use the same single parameter in order for them to work correctly as well. so, don't stress out about trying to understand every little detail right now -- just focus on getting the simple parts working correctly first, and then move on to more complex parts later when you feel more confident and comfortable with the basic concepts. just remember that this function is designed specifically for your needs and should always be used exactly as described in the documentation or example code provided by Apple.
```objc
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
if ([action isEqualToString:@selector(select)]) {
return NO;
} else if ([action isEqualToString:@selector(selectAll)]) {
return NO;
} else {
return [super canPerformAction:action withSender:sender];
}
}
- (void)cut:(id)sender {
[self copy:sender];
[imageView setHidden:YES];
}
- (void)copy:(id)sender {
[self placeImageOnPasteboard:[self imageView]];
}
- (void)paste:(id)sender {
UIPasteboard *appPasteBoard =[UIPasteboard pasteboardWithName:@"CopyPasteImage" create:YES];
NSData *data =[appPasteBoard dataForPasteboardType:@"com.marizack.CopyPasteImage.imageView"];
pasteView.image = [UIImage imageWithData:data];
}
```
效果:
1、点击图片,显示菜单按钮。
2、点击复制,将数据复制到剪贴板上。
3、点击粘贴,将数据粘贴到uiimageview上。