123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- // 代码地址: https://github.com/CoderMJLee/MJRefresh
- #import <UIKit/UIKit.h>
- #import <objc/message.h>
- #import <objc/runtime.h>
- // 弱引用
- #define MJWeakSelf __weak typeof(self) weakSelf = self;
- // 日志输出
- #ifdef DEBUG
- #define MJRefreshLog(...) NSLog(__VA_ARGS__)
- #else
- #define MJRefreshLog(...)
- #endif
- // 过期提醒
- #define MJRefreshDeprecated(DESCRIPTION) __attribute__((deprecated(DESCRIPTION)))
- // 运行时objc_msgSend
- #define MJRefreshMsgSend(...) ((void (*)(void *, SEL, UIView *))objc_msgSend)(__VA_ARGS__)
- #define MJRefreshMsgTarget(target) (__bridge void *)(target)
- // RGB颜色
- #define MJRefreshColor(r, g, b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1.0]
- // 文字颜色
- #define MJRefreshLabelTextColor MJRefreshColor(90, 90, 90)
- // 字体大小
- #define MJRefreshLabelFont [UIFont boldSystemFontOfSize:14]
- // 常量
- UIKIT_EXTERN const CGFloat MJRefreshLabelLeftInset;
- UIKIT_EXTERN const CGFloat MJRefreshHeaderHeight;
- UIKIT_EXTERN const CGFloat MJRefreshFooterHeight;
- UIKIT_EXTERN const CGFloat MJRefreshTrailWidth;
- UIKIT_EXTERN const CGFloat MJRefreshFastAnimationDuration;
- UIKIT_EXTERN const CGFloat MJRefreshSlowAnimationDuration;
- UIKIT_EXTERN NSString *const MJRefreshKeyPathContentOffset;
- UIKIT_EXTERN NSString *const MJRefreshKeyPathContentSize;
- UIKIT_EXTERN NSString *const MJRefreshKeyPathContentInset;
- UIKIT_EXTERN NSString *const MJRefreshKeyPathPanState;
- UIKIT_EXTERN NSString *const MJRefreshHeaderLastUpdatedTimeKey;
- UIKIT_EXTERN NSString *const MJRefreshHeaderIdleText;
- UIKIT_EXTERN NSString *const MJRefreshHeaderPullingText;
- UIKIT_EXTERN NSString *const MJRefreshHeaderRefreshingText;
- UIKIT_EXTERN NSString *const MJRefreshTrailerIdleText;
- UIKIT_EXTERN NSString *const MJRefreshTrailerPullingText;
- UIKIT_EXTERN NSString *const MJRefreshAutoFooterIdleText;
- UIKIT_EXTERN NSString *const MJRefreshAutoFooterRefreshingText;
- UIKIT_EXTERN NSString *const MJRefreshAutoFooterNoMoreDataText;
- UIKIT_EXTERN NSString *const MJRefreshBackFooterIdleText;
- UIKIT_EXTERN NSString *const MJRefreshBackFooterPullingText;
- UIKIT_EXTERN NSString *const MJRefreshBackFooterRefreshingText;
- UIKIT_EXTERN NSString *const MJRefreshBackFooterNoMoreDataText;
- UIKIT_EXTERN NSString *const MJRefreshHeaderLastTimeText;
- UIKIT_EXTERN NSString *const MJRefreshHeaderDateTodayText;
- UIKIT_EXTERN NSString *const MJRefreshHeaderNoneLastDateText;
- UIKIT_EXTERN NSString *const MJRefreshDidChangeLanguageNotification;
- // 状态检查
- #define MJRefreshCheckState \
- MJRefreshState oldState = self.state; \
- if (state == oldState) return; \
- [super setState:state];
- // 异步主线程执行,不强持有Self
- #define MJRefreshDispatchAsyncOnMainQueue(x) \
- __weak typeof(self) weakSelf = self; \
- dispatch_async(dispatch_get_main_queue(), ^{ \
- typeof(weakSelf) self = weakSelf; \
- {x} \
- });
- /// 替换方法实现
- /// @param _fromClass 源类
- /// @param _originSelector 源类的 Selector
- /// @param _toClass 目标类
- /// @param _newSelector 目标类的 Selector
- CG_INLINE BOOL MJRefreshExchangeImplementations(
- Class _fromClass, SEL _originSelector,
- Class _toClass, SEL _newSelector) {
- if (!_fromClass || !_toClass) {
- return NO;
- }
-
- Method oriMethod = class_getInstanceMethod(_fromClass, _originSelector);
- Method newMethod = class_getInstanceMethod(_toClass, _newSelector);
- if (!newMethod) {
- return NO;
- }
-
- BOOL isAddedMethod = class_addMethod(_fromClass, _originSelector,
- method_getImplementation(newMethod),
- method_getTypeEncoding(newMethod));
- if (isAddedMethod) {
- // 如果 class_addMethod 成功了,说明之前 fromClass 里并不存在 originSelector,所以要用一个空的方法代替它,以避免 class_replaceMethod 后,后续 toClass 的这个方法被调用时可能会 crash
- IMP emptyIMP = imp_implementationWithBlock(^(id selfObject) {});
- IMP oriMethodIMP = method_getImplementation(oriMethod) ?: emptyIMP;
- const char *oriMethodTypeEncoding = method_getTypeEncoding(oriMethod) ?: "v@:";
- class_replaceMethod(_toClass, _newSelector, oriMethodIMP, oriMethodTypeEncoding);
- } else {
- method_exchangeImplementations(oriMethod, newMethod);
- }
- return YES;
- }
|