iOS runtimeはbuttonの繰り返しクリックの問題を解決します
3942 ワード
runtimeとは?
OCはランタイム言語であり、OCは最下位のC言語apiを提供し、コンパイラは最終的にOCコードをランタイムコードに変換します.端末コマンド:clang-rewrite-objc.mは後に便利なものが見える.cpp(c++ファイル).呼び出し方法の本質はruntimeが提供するobjc_を利用することである.msgSend()はメッセージを送信します.
runtimeは何ができますか?
例えば、a動的交換の2つのメソッドの実装(特に交換システムが持参するメソッド)b動的にオブジェクトを追加するメンバー変数とメンバーメソッドcあるクラスのすべてのメンバーメソッド、メンバー変数を取得する
runtimeの応用
1、いくつかのOCコードを実行時コードに変えて、blockの実現原理などの下層を探究する.2、ブロックシステムが持参した方法呼び出し;3、catagory(分類では属性を設定できない)を実現し、runtimeが提供する方法でも属性を増やすことができる.setメソッド:objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy); value:新しい値、object:オブジェクトを格納し、key:keyで値を取得できます.policy:ポリシーassigncopyretian(strong)を格納します.getメソッド:objc_getAssociatedObject(id object, const void *key); 4、NSCordingの自動アーカイブと自動アーカイブを実現する;5、辞書とモデルの自動変換を実現する.
実用的な例
ユーザーの動作が制御できないため、ボタンを連続的にクリックすると、ボタンの繰り返しイベントが呼び出される可能性があります.潤runtimeメカニズムを使用して、ボタンに制御可能な連続クリック間隔を追加し、ボタンをクリックした後、クリックできず、再びクリック可能な状態に戻る時間を制御することができれば、問題は解決します.そこで、UIButtonにリストを追加し、eventTimeIntervalプロパティを追加してこの問題を解決することを選択しました.
コードは次のとおりです.
OCはランタイム言語であり、OCは最下位のC言語apiを提供し、コンパイラは最終的にOCコードをランタイムコードに変換します.端末コマンド:clang-rewrite-objc.mは後に便利なものが見える.cpp(c++ファイル).呼び出し方法の本質はruntimeが提供するobjc_を利用することである.msgSend()はメッセージを送信します.
runtimeは何ができますか?
例えば、a動的交換の2つのメソッドの実装(特に交換システムが持参するメソッド)b動的にオブジェクトを追加するメンバー変数とメンバーメソッドcあるクラスのすべてのメンバーメソッド、メンバー変数を取得する
runtimeの応用
1、いくつかのOCコードを実行時コードに変えて、blockの実現原理などの下層を探究する.2、ブロックシステムが持参した方法呼び出し;3、catagory(分類では属性を設定できない)を実現し、runtimeが提供する方法でも属性を増やすことができる.setメソッド:objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy); value:新しい値、object:オブジェクトを格納し、key:keyで値を取得できます.policy:ポリシーassigncopyretian(strong)を格納します.getメソッド:objc_getAssociatedObject(id object, const void *key); 4、NSCordingの自動アーカイブと自動アーカイブを実現する;5、辞書とモデルの自動変換を実現する.
実用的な例
ユーザーの動作が制御できないため、ボタンを連続的にクリックすると、ボタンの繰り返しイベントが呼び出される可能性があります.潤runtimeメカニズムを使用して、ボタンに制御可能な連続クリック間隔を追加し、ボタンをクリックした後、クリックできず、再びクリック可能な状態に戻る時間を制御することができれば、問題は解決します.そこで、UIButtonにリストを追加し、eventTimeIntervalプロパティを追加してこの問題を解決することを選択しました.
コードは次のとおりです.
// UIButton+Click.h
#import
@interface UIButton (Click)
// objc_getAssociatedObject、objc_setAssociatedObject
@property (nonatomic, assign) NSTimeInterval eventTimeInterval;
@end
//UIButton+QYBtnTimer.m
#import "UIButton+Click.h"
#import
#define defaultInterval 0.0003 // , ,
@interface UIButton ()
/**
* bool YES NO
*/
@property (nonatomic, assign) BOOL isIgnoreEvent;
@end
@implementation UIButton (Click)
static const char *UIControl_eventTimeInterval = "UIControl_eventTimeInterval";
static const char *UIControl_enventIsIgnoreEvent = "UIControl_enventIsIgnoreEvent";
+ (void)load {
// Method Swizzling
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// selector Method
SEL selA = @selector(sendAction:to:forEvent:);
SEL selB = @selector(new_sendAction:to:forEvent:);
Method methodA = class_getInstanceMethod(self,selA);
Method methodB = class_getInstanceMethod(self, selB);
//
BOOL isAdd = class_addMethod(self, selA, method_getImplementation(methodB), method_getTypeEncoding(methodB));
if (isAdd) {// ->
class_replaceMethod(self, selB, method_getImplementation(methodA), method_getTypeEncoding(methodA));
}else{// ->
// methodB , methodA methodB IMP 。
method_exchangeImplementations(methodA, methodB);
}
});
}
- (void)new_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {
self.eventTimeInterval = self.eventTimeInterval == 0 ? defaultInterval : self.eventTimeInterval;
if (self.isIgnoreEvent){//
return;
}else if (self.eventTimeInterval > 0){// , eventTimeInterval ,
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(self.eventTimeInterval * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self setIsIgnoreEvent:NO];
});
}
self.isIgnoreEvent = YES;//
// , sendAction:to:forEvent: ,
// sendAction:to:forEvent: , 。
[self new_sendAction:action to:target forEvent:event];
}
// runtime
- (BOOL)isIgnoreEvent{
return [objc_getAssociatedObject(self, UIControl_enventIsIgnoreEvent) boolValue];
}
- (void)setIsIgnoreEvent:(BOOL)isIgnoreEvent {
objc_setAssociatedObject(self, UIControl_enventIsIgnoreEvent, @(isIgnoreEvent), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSTimeInterval)eventTimeInterval {
return [objc_getAssociatedObject(self, UIControl_eventTimeInterval) doubleValue];
}
- (void)setEventTimeInterval:(NSTimeInterval)eventTimeInterval {
objc_setAssociatedObject(self, UIControl_eventTimeInterval, @(eventTimeInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end