MJRefreshConst.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. // 代码地址: https://github.com/CoderMJLee/MJRefresh
  2. #import <UIKit/UIKit.h>
  3. #import <objc/message.h>
  4. #import <objc/runtime.h>
  5. // 弱引用
  6. #define MJWeakSelf __weak typeof(self) weakSelf = self;
  7. // 日志输出
  8. #ifdef DEBUG
  9. #define MJRefreshLog(...) NSLog(__VA_ARGS__)
  10. #else
  11. #define MJRefreshLog(...)
  12. #endif
  13. #ifndef mj_cguard
  14. #define mj_cguard(X) if (X);
  15. #endif
  16. // 过期提醒
  17. #define MJRefreshDeprecated(DESCRIPTION) __attribute__((deprecated(DESCRIPTION)))
  18. // 运行时objc_msgSend
  19. #define MJRefreshMsgSend(...) ((void (*)(void *, SEL, UIView *))objc_msgSend)(__VA_ARGS__)
  20. #define MJRefreshMsgTarget(target) (__bridge void *)(target)
  21. // RGB颜色
  22. #define MJRefreshColor(r, g, b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1.0]
  23. // 文字颜色
  24. #define MJRefreshLabelTextColor MJRefreshColor(90, 90, 90)
  25. // 字体大小
  26. #define MJRefreshLabelFont [UIFont boldSystemFontOfSize:14]
  27. // 常量
  28. UIKIT_EXTERN const CGFloat MJRefreshLabelLeftInset;
  29. UIKIT_EXTERN const CGFloat MJRefreshHeaderHeight;
  30. UIKIT_EXTERN const CGFloat MJRefreshFooterHeight;
  31. UIKIT_EXTERN const CGFloat MJRefreshTrailWidth;
  32. UIKIT_EXTERN const CGFloat MJRefreshFastAnimationDuration;
  33. UIKIT_EXTERN const CGFloat MJRefreshSlowAnimationDuration;
  34. UIKIT_EXTERN NSString *const MJRefreshKeyPathContentOffset;
  35. UIKIT_EXTERN NSString *const MJRefreshKeyPathContentSize;
  36. UIKIT_EXTERN NSString *const MJRefreshKeyPathContentInset;
  37. UIKIT_EXTERN NSString *const MJRefreshKeyPathPanState;
  38. UIKIT_EXTERN NSString *const MJRefreshHeaderLastUpdatedTimeKey;
  39. UIKIT_EXTERN NSString *const MJRefreshHeaderIdleText;
  40. UIKIT_EXTERN NSString *const MJRefreshHeaderPullingText;
  41. UIKIT_EXTERN NSString *const MJRefreshHeaderRefreshingText;
  42. UIKIT_EXTERN NSString *const MJRefreshTrailerIdleText;
  43. UIKIT_EXTERN NSString *const MJRefreshTrailerPullingText;
  44. UIKIT_EXTERN NSString *const MJRefreshAutoFooterIdleText;
  45. UIKIT_EXTERN NSString *const MJRefreshAutoFooterRefreshingText;
  46. UIKIT_EXTERN NSString *const MJRefreshAutoFooterNoMoreDataText;
  47. UIKIT_EXTERN NSString *const MJRefreshBackFooterIdleText;
  48. UIKIT_EXTERN NSString *const MJRefreshBackFooterPullingText;
  49. UIKIT_EXTERN NSString *const MJRefreshBackFooterRefreshingText;
  50. UIKIT_EXTERN NSString *const MJRefreshBackFooterNoMoreDataText;
  51. UIKIT_EXTERN NSString *const MJRefreshHeaderLastTimeText;
  52. UIKIT_EXTERN NSString *const MJRefreshHeaderDateTodayText;
  53. UIKIT_EXTERN NSString *const MJRefreshHeaderNoneLastDateText;
  54. UIKIT_EXTERN NSString *const MJRefreshDidChangeLanguageNotification;
  55. // 状态检查
  56. #define MJRefreshCheckState \
  57. MJRefreshState oldState = self.state; \
  58. if (state == oldState) return; \
  59. [super setState:state];
  60. // 异步主线程执行,不强持有Self
  61. #define MJRefreshDispatchAsyncOnMainQueue(x) \
  62. __weak typeof(self) weakSelf = self; \
  63. dispatch_async(dispatch_get_main_queue(), ^{ \
  64. typeof(weakSelf) self = weakSelf; \
  65. {x} \
  66. });
  67. /// 替换方法实现
  68. /// @param _fromClass 源类
  69. /// @param _originSelector 源类的 Selector
  70. /// @param _toClass 目标类
  71. /// @param _newSelector 目标类的 Selector
  72. CG_INLINE BOOL MJRefreshExchangeImplementations(
  73. Class _fromClass, SEL _originSelector,
  74. Class _toClass, SEL _newSelector) {
  75. if (!_fromClass || !_toClass) {
  76. return NO;
  77. }
  78. Method oriMethod = class_getInstanceMethod(_fromClass, _originSelector);
  79. Method newMethod = class_getInstanceMethod(_toClass, _newSelector);
  80. if (!newMethod) {
  81. return NO;
  82. }
  83. BOOL isAddedMethod = class_addMethod(_fromClass, _originSelector,
  84. method_getImplementation(newMethod),
  85. method_getTypeEncoding(newMethod));
  86. if (isAddedMethod) {
  87. // 如果 class_addMethod 成功了,说明之前 fromClass 里并不存在 originSelector,所以要用一个空的方法代替它,以避免 class_replaceMethod 后,后续 toClass 的这个方法被调用时可能会 crash
  88. IMP emptyIMP = imp_implementationWithBlock(^(id selfObject) {});
  89. IMP oriMethodIMP = method_getImplementation(oriMethod) ?: emptyIMP;
  90. const char *oriMethodTypeEncoding = method_getTypeEncoding(oriMethod) ?: "v@:";
  91. class_replaceMethod(_toClass, _newSelector, oriMethodIMP, oriMethodTypeEncoding);
  92. } else {
  93. method_exchangeImplementations(oriMethod, newMethod);
  94. }
  95. return YES;
  96. }