MJRefreshConst.h 4.3 KB

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