背景介紹
學(xué)習(xí)Swift的時(shí)候?qū)懝ぞ哳惖臅r(shí)候突發(fā)奇想,想要使用block代替selector,嘗試了很多次,最后還是無能為力,后來想到在oc中遇到過BlocksKit,遂學(xué)習(xí)參考了一下筛圆,但是用到了runtime,無法在純Swift的項(xiàng)目中使用,如果使用oc與swift混編的話則可以達(dá)到效果椿浓,在此記錄
OC
下面是在UIView的分類中聲明的兩個(gè)方法太援,為了給View添加一個(gè)點(diǎn)擊事件,如同控件button一樣扳碍,下面兩個(gè)方法的效果一樣
@interface UIView (Helper)
-(void)addTapAction:(SEL)action forTarget:(id) aTarget;
-(id)addTapActionBlock:(void (^)(id sender))action;
@end
下面是對(duì)兩個(gè)方法的實(shí)現(xiàn)提岔,第一個(gè)方法直接將sel傳遞,第二個(gè)方法是通過運(yùn)行時(shí)的兩個(gè)方法相當(dāng)于先將block通過key保存起來然后再拿出來調(diào)用block(暫時(shí)先這么理解笋敞,因?yàn)槲矣X得不是那么簡(jiǎn)單碱蒙,后面會(huì)更改見解)
OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key)
#import "UIView+Helper.h"
#import <QuartzCore/QuartzCore.h>
#import <objc/runtime.h>
@implementation UIView (Helper)
-(void)addTapAction:(SEL)action forTarget:(id) aTarget
{
self.userInteractionEnabled=YES;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:aTarget action:action];
[self addGestureRecognizer:tap];
}
- (id)addTapActionBlock:(void (^)(id sender))action{
self.userInteractionEnabled=YES;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(testHandle:)];
[self addGestureRecognizer:tap];
if (!self) return nil;
objc_setAssociatedObject(self, @"qeqweqeqweqeweretertet", action, OBJC_ASSOCIATION_COPY_NONATOMIC);
return self;
}
- (void)testHandle:(id)sender{
void (^block)(id) = objc_getAssociatedObject(self, @"qeqweqeqweqeweretertet");
if (block) block(self);
}
@end
Swift
在swift中實(shí)現(xiàn)上面的block方式添加點(diǎn)擊事件
首先看下面兩行oc的代碼,注意key為“ UnsafeRawPointer”格式夯巷,不可以直接用String字符串赛惩,我之前用的字符串一直報(bào)nil錯(cuò)
public func objc_setAssociatedObject(_ object: Any!, _ key: UnsafeRawPointer!, _ value: Any!, _ policy: objc_AssociationPolicy)
public func objc_getAssociatedObject(_ object: Any!, _ key: UnsafeRawPointer!) -> Any!
然后在UIView的擴(kuò)展文件中寫下面代碼
import Foundation//
struct RuntimeKey {//聲名runtime的key值
static let viewTapKey = UnsafeRawPointer.init(bitPattern: "ViewTapKey".hashValue)
}
extension UIView{
func addTapActionBlock(action : UIViewCategoryActionBlock?) {
self.isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target:self, action:#selector(UIView.testHandle))
self.addGestureRecognizer(tap)
objc_setAssociatedObject(self, RuntimeKey.viewTapKey, action, .OBJC_ASSOCIATION_COPY_NONATOMIC)//此處相當(dāng)于保存block
}
func testHandle() {
let block = objc_getAssociatedObject(self, RuntimeKey.viewTapKey) as! UIViewCategoryActionBlock//此處相當(dāng)于提取block
block()
}
}