更新記錄
- 2020年3月28日,初稿
文章背景
近日,接到頭頭突然讓我改一個東西,讓我馬上把某個按鈕的點擊相應區域擴大一點。作為一個iOS三個月的新人,還真不了解要怎么做。隨后,頭頭說只要加一行代碼就行了,然后讓某位前輩直接把參考代碼發給我。
后來,我加了一行類似於如下的代碼:
[button setHitTestEdgeInsets:UIEdgeInsetsMake(-10, -10, -10, -10)];
就使得按鈕點擊區域擴大了。但是,我不明白其中的原理。於是乎,想要一探究竟。
探索過程
- 網上搜索
iOS擴展按鈕點擊區域
,發現有一個千篇一律的方法:
增加UIButton的點擊范圍,那么從中也可以窺探出,這個方法大概率就是業界常用的,擴大按鈕點擊區域的方法。 - 上述鏈接可以優化的一點的是:
不要重寫UIButton類的pointInside:withEvent:方法,使用swizzle交換IMP
- 具體源碼如下:
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSError *error = nil;
[self jr_swizzleMethod:@selector(pointInside:withEvent:) withMethod:@selector(hitTest_pointInside:withEvent:) error:&error];
NSAssert(!error, @"UIView+HitTest.h swizzling failed: error = %@", error);
});
}
- (BOOL)hitTest_pointInside:(CGPoint)point withEvent:(UIEvent *)event {
if (UIEdgeInsetsEqualToEdgeInsets(self.hitTestEdgeInsets, UIEdgeInsetsZero)) {
return [self hitTest_pointInside:point withEvent:event];
}
CGRect relativeFrame = self.bounds;
CGRect hitFrame = UIEdgeInsetsInsetRect(relativeFrame, self.hitTestEdgeInsets);
return CGRectContainsPoint(hitFrame, point);
}
探索其中的知識點
dispatch_once
- 源碼及原理可參考玩轉dispatch_once
- 原理還是挺深入的,在此不便深入。僅知道可以保證只初始化一次,且保證多線程安全。(可和Java中的單例模式Double CheckLock初始化比較一下)
關聯對象(如何給分類添加屬性)
- 參考iOS 給分類(Category文件)添加屬性
- 底層原理實現,可參考iOS關聯對象技術原理
CGRectInset
事件響應鏈
- 在這個例子中的使用還是很簡單的。通過
pointInside:withEvent:
函數判斷,該點擊點是否在該view的點擊范圍內,否則就往時間響應鏈的下游傳遞。
寫在后面的話
- 因為剛入門iOS,而且工作的大多時間都花在業務邏輯上,對iOS基礎知識這一塊還很不熟悉。本例中的很多知識點,我也是解除了這個例子之后我才了解得到。
- 所以這篇文章也是比較水,沒有什么深度,僅作為自己初級學習過程中的一個總結。
- 這里的不少知識點,沒有過多地寫個人總結,因為本身也是比較簡單的知識,網上搜索已經有一大堆的參考了。