iOS UILABEL \UIIMAGE複製

Night-Wish發表於2014-02-20

在iOS中下面三個控制元件,自身就有複製-貼上的功能:

 1、UITextView

 2、UITextField

 3、UIWebView

 

UIKit framework提供了幾個類和協議方便我們在自己的應用程式中實現剪貼簿的功能。

 1、UIPasteboard:我們可以向其中寫入資料,也可以讀取資料
 2、UIMenuController:顯示一個快捷選單,用來展示覆制、剪貼、貼上等選擇的項。
 3、UIResponder中的 canPerformAction:withSender:用於控制哪些命令顯示在快捷選單中。
 4、當快捷選單上的命令點選的時候,UIResponderStandardEditActions將會被呼叫。

 下面這些項能被放置到剪貼簿中

 1、UIPasteboardTypeListString —   字串陣列, 包含kUTTypeUTF8PlainText
 2、UIPasteboardTypeListURL —   URL陣列,包含kUTTypeURL
 3、UIPasteboardTypeListImage —   圖形陣列, 包含kUTTypePNG 和kUTTypeJPEG
 4、UIPasteboardTypeListColor —   顏色陣列

 剪貼簿的型別分為兩種:
 系統級:使用UIPasteboardNameGeneralUIPasteboardNameFind,系統級應用程式關閉,或者解除安裝的資料不會丟失。

 應用程式級:通過設定,可以讓資料在應用程式關閉之後仍然儲存在剪貼簿中,但是應用程式解除安裝之後資料就會失去。我們可用通過pasteboardWithName:create:來建立。

 

例子如下:

有時候我們可能需要複製UILabel上的文字,或者UIImageView的圖片,而UILabel和UIImageView預設是不響應Touch事件的,也無法複製,那麼我們就需要自己實現一個可複製的UILabel。新新增一個類繼承自UILabel:

<a target=_blank href="http://shop111849857.taobao.com/shop/view_shop.htm?spm=a1z0e.1.10010.4.Dadm77">@interface UICopyLabel : UILabel  
@end  

#import "UICopyLabel.h"  
@implementation UICopyLabel  
@end  </a>

 

為了能接收到事件(能成為第一響應者),我們需要覆蓋一個方法:

<a target=_blank href="http://shop111849857.taobao.com/shop/view_shop.htm?spm=a1z0e.1.10010.4.Dadm77">-(BOOL)canBecomeFirstResponder
{  
    return YES;  
}  </a>

 

 還需要針對複製的操作覆蓋兩個方法: 

<a target=_blank href="http://shop111849857.taobao.com/shop/view_shop.htm?spm=a1z0e.1.10010.4.Dadm77">// 可以響應的方法
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender
{  
    return (action == @selector(copy:));  
}  </a>

 

 

<a target=_blank href="http://shop111849857.taobao.com/shop/view_shop.htm?spm=a1z0e.1.10010.4.Dadm77">//針對於響應方法的實現  
-(void)copy:(id)sender
{  
    UIPasteboard *pboard = [UIPasteboard generalPasteboard];  
    pboard.string = self.text;  
}  </a>

 

有了以上三個方法,我們就能處理copy了,當然,在能接收到事件的情況下:

 

<a target=_blank href="http://shop111849857.taobao.com/shop/view_shop.htm?spm=a1z0e.1.10010.4.Dadm77">//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];  
}  </a>

 

我們已經可以接收到事件了!由於我在上方將tap數設為2,所以需要雙擊才能捕獲,接下來,我們需要處理這個tap,以便讓選單欄彈出來:

<a target=_blank href="http://shop111849857.taobao.com/shop/view_shop.htm?spm=a1z0e.1.10010.4.Dadm77">-(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];
}  </a>

 這樣一來,一個可複製的UILabel就誕生了!它能處理接收點選、彈出選單欄、處理copy,這是一個很普通的可複製控制元件。

接下來我們做一個可複製的UIImageView,建立一個新的viewController,放兩個imageView,預設顯示不同的圖:
然後把上面的程式碼直接拷過來,改三個地方:

<a target=_blank href="http://shop111849857.taobao.com/shop/view_shop.htm?spm=a1z0e.1.10010.4.Dadm77">-(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;  
}  </a>

 UIPasteboard有系統級別和應用級別兩種型別,所以不僅可以在應用程式內通訊,還能在應用程式間通訊,比如我複製一個url,然後開啟safari,貼上到位址列去,而我們可以在應用程式間通訊、共享資料。

在PasteBoardWrite裡面點“寫入”後把textField中的文字寫入貼上板,然後切換到PasteBoardRead的時候顯示出來。如果我們的貼上板只想給“自己人”用的話,就不能用系統的通用貼上板,需要我們自己建立一個:

<a target=_blank href="http://shop111849857.taobao.com/shop/view_shop.htm?spm=a1z0e.1.10010.4.Dadm77">//需要提供一個唯一的名字,一般使用倒寫的域名:com.mycompany.myapp.pboard  
//後面的參數列示,如果不存在,是否建立一個  
UIPasteboard *pb = [UIPasteboard pasteboardWithName:@"testBoard" create:YES];  </a>

使用這個貼上板,我們可以把文字存進去,然後在另一個app裡面讀出來,一些常用的型別已經被設定為屬性了: 


除此之外,如果是能夠轉換成plist的資料型別(NSString, NSArray, NSDictionary, NSDate, NSNumber 和 NSURL),我們可以呼叫setValue:forPasteboardType:方法去儲存資料,其他型別只能呼叫setData:forPasteboardType:方法(plist資料型別也可使用),類似於這樣:

 

<a target=_blank href="http://shop111849857.taobao.com/shop/view_shop.htm?spm=a1z0e.1.10010.4.Dadm77">//儲存資料
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"];  </a>

上面提到了一個PasteboardType,這是一個統一型別識別符號(Uniform Type Identifier  UTI),能幫助app獲取自己能處理的資料。比如你只能處理文字的貼上,那給你一個UIImage顯然是無用的。你可以使用公用的UTI,也可以使用任意字元,蘋果建議使用倒寫的域名加上型別名:com.myCompany.myApp.myType。

相關文章