Commit 33c9d396 authored by jz's avatar jz

替换为最新MJRe

parent 8e66581b
......@@ -213,7 +213,6 @@
6003F587195388D20070C39A /* Frameworks */,
6003F588195388D20070C39A /* Resources */,
88C96FFAE5ACFCA8DAE2E535 /* [CP] Embed Pods Frameworks */,
AC731551ACD6686FC4DB21B0 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
......@@ -232,8 +231,6 @@
6003F5AA195388D20070C39A /* Sources */,
6003F5AB195388D20070C39A /* Frameworks */,
6003F5AC195388D20070C39A /* Resources */,
AC94AF4168D3DD1E67AAB021 /* [CP] Embed Pods Frameworks */,
B24157C697F0666FDF323615 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
......@@ -326,7 +323,7 @@
files = (
);
inputPaths = (
"${SRCROOT}/Pods/Target Support Files/Pods-GMRefresh_Example/Pods-GMRefresh_Example-frameworks.sh",
"${PODS_ROOT}/Target Support Files/Pods-GMRefresh_Example/Pods-GMRefresh_Example-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/GMCache/GMCache.framework",
"${BUILT_PRODUCTS_DIR}/GMKit/GMKit.framework",
"${BUILT_PRODUCTS_DIR}/GMPhobos/GMPhobos.framework",
......@@ -347,52 +344,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-GMRefresh_Example/Pods-GMRefresh_Example-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
AC731551ACD6686FC4DB21B0 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Copy Pods Resources";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-GMRefresh_Example/Pods-GMRefresh_Example-resources.sh\"\n";
showEnvVarsInLog = 0;
};
AC94AF4168D3DD1E67AAB021 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-GMRefresh_Tests/Pods-GMRefresh_Tests-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
B24157C697F0666FDF323615 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "[CP] Copy Pods Resources";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-GMRefresh_Tests/Pods-GMRefresh_Tests-resources.sh\"\n";
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-GMRefresh_Example/Pods-GMRefresh_Example-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
BD53463213654FBF55212ABA /* [CP] Check Pods Manifest.lock */ = {
......
PODS:
- GMCache (0.1.1):
- TMCache (~> 2.1.0)
- GMKit (0.7.41):
- GMKit/Category (= 0.7.41)
- GMKit/Color (= 0.7.41)
- GMKit/Constant (= 0.7.41)
- GMKit/FDFullscreenPopGesture (= 0.7.41)
- GMKit/Kit (= 0.7.41)
- GMKit/Protocol (= 0.7.41)
- Masonry (= 1.1.0)
- SDWebImage (= 3.7.6)
- GMKit/Category (0.7.41):
- GMKit/Color (= 0.7.41)
- GMKit/Constant (= 0.7.41)
- GMKit/Protocol (= 0.7.41)
- Masonry (= 1.1.0)
- SDWebImage (= 3.7.6)
- GMKit/Color (0.7.41):
- Masonry (= 1.1.0)
- SDWebImage (= 3.7.6)
- GMKit/Constant (0.7.41):
- Masonry (= 1.1.0)
- SDWebImage (= 3.7.6)
- GMKit/FDFullscreenPopGesture (0.7.41):
- Masonry (= 1.1.0)
- SDWebImage (= 3.7.6)
- GMKit/Kit (0.7.41):
- GMKit/Category (= 0.7.41)
- GMKit/Color (= 0.7.41)
- GMKit/Constant (= 0.7.41)
- GMKit/Protocol (= 0.7.41)
- Masonry (= 1.1.0)
- SDWebImage (= 3.7.6)
- GMKit/Protocol (0.7.41):
- Masonry (= 1.1.0)
- SDWebImage (= 3.7.6)
- GMPhobos (0.4.6):
- GMCache (~> 0.1.1)
- GMCache (1.0.1):
- TMCache (= 2.1.0)
- GMKit (1.1.4):
- GMKit/Category (= 1.1.4)
- GMKit/Color (= 1.1.4)
- GMKit/Constant (= 1.1.4)
- GMKit/FDFullscreenPopGesture (= 1.1.4)
- GMKit/Kit (= 1.1.4)
- GMKit/Protocol (= 1.1.4)
- Masonry
- SDWebImage
- GMKit/Category (1.1.4):
- GMKit/Color (= 1.1.4)
- GMKit/Constant (= 1.1.4)
- GMKit/Protocol (= 1.1.4)
- Masonry
- SDWebImage
- GMKit/Color (1.1.4):
- Masonry
- SDWebImage
- GMKit/Constant (1.1.4):
- Masonry
- SDWebImage
- GMKit/FDFullscreenPopGesture (1.1.4):
- Masonry
- SDWebImage
- GMKit/Kit (1.1.4):
- GMKit/Category (= 1.1.4)
- GMKit/Color (= 1.1.4)
- GMKit/Constant (= 1.1.4)
- GMKit/Protocol (= 1.1.4)
- Masonry
- SDWebImage
- GMKit/Protocol (1.1.4):
- Masonry
- SDWebImage
- GMPhobos (1.3.4):
- GMCache
- GMKit
- GMRefresh (0.1.81):
- GMRefresh (1.0.3):
- GMPhobos
- Masonry (1.1.0)
- SDWebImage (3.7.6):
- SDWebImage/Core (= 3.7.6)
- SDWebImage/Core (3.7.6)
- SDWebImage (5.3.1):
- SDWebImage/Core (= 5.3.1)
- SDWebImage/Core (5.3.1)
- TMCache (2.1.0)
DEPENDENCIES:
- GMRefresh (from `../`)
SPEC REPOS:
"git@git.wanmeizhensuo.com:gengmeiios/GMSpecs.git":
- GMCache
- GMKit
- GMPhobos
https://github.com/cocoapods/specs.git:
- Masonry
- SDWebImage
- TMCache
EXTERNAL SOURCES:
GMRefresh:
:path: ../
:path: "../"
SPEC CHECKSUMS:
GMCache: 73855b613b9d7e34f4f37ad425e8b8153b760c04
GMKit: 4820e0eb7727735f88fb2f983f178edd074343c1
GMPhobos: 4a6dcf21fe2e1f81ac7761217bff1a92655dc88c
GMRefresh: d818f36645fb714ae54292e18ce7e0cb6d5c2a1c
GMCache: b78d8e46db864405e91d226ce640cc80d966c611
GMKit: 11c9ab9a317f381a05b0e1e577dd95a495625edf
GMPhobos: 6c7ae144997ace1661fe315adcc78c394cb73291
GMRefresh: 16d96e530312cd5b26a21c939437fa88829dad54
Masonry: 678fab65091a9290e40e2832a55e7ab731aad201
SDWebImage: c325cf02c30337336b95beff20a13df489ec0ec9
SDWebImage: 7137d57385fb632129838c1e6ab9528a22c666cc
TMCache: 95ebcc9b3c7e90fb5fd8fc3036cba3aa781c9bed
PODFILE CHECKSUM: a967856f0f3fe38865db489c22abaf1fecccf026
COCOAPODS: 1.3.1
COCOAPODS: 1.7.4
......@@ -8,6 +8,8 @@
#import "MJRefreshFooter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MJRefreshAutoFooter : MJRefreshFooter
/** 是否自动刷新(默认为YES) */
@property (assign, nonatomic, getter=isAutomaticallyRefresh) BOOL automaticallyRefresh;
......@@ -17,4 +19,12 @@
/** 当底部控件出现多少时就自动刷新(默认为1.0,也就是底部控件完全出现时,才会自动刷新) */
@property (assign, nonatomic) CGFloat triggerAutomaticallyRefreshPercent;
/** 是否每一次拖拽只发一次请求 */
@property (assign, nonatomic, getter=isOnlyRefreshPerDrag) BOOL onlyRefreshPerDrag;
/** 在触发开始刷新前的刷新忽略逻辑, 默认由 isOnlyRefreshPerDrag 和 新手势决定, 用于特殊控制逻辑, 如果不清楚机制, 请勿使用 */
- (BOOL)ignoreRefreshAction NS_REQUIRES_SUPER;
@end
NS_ASSUME_NONNULL_END
......@@ -9,6 +9,8 @@
#import "MJRefreshAutoFooter.h"
@interface MJRefreshAutoFooter()
/** 一个新的拖拽 */
@property (assign, nonatomic, getter=isOneNewPan) BOOL oneNewPan;
@end
@implementation MJRefreshAutoFooter
......@@ -53,6 +55,9 @@
// 设置为默认状态
self.automaticallyRefresh = YES;
// 默认是当offset达到条件就发送请求(可连续)
self.onlyRefreshPerDrag = YES;
}
- (void)scrollViewContentSizeDidChange:(NSDictionary *)change
......@@ -60,7 +65,7 @@
[super scrollViewContentSizeDidChange:change];
// 设置位置
self.mj_y = self.scrollView.mj_contentH;
self.mj_y = self.scrollView.mj_contentH + self.ignoredScrollViewContentInsetBottom;
}
- (void)scrollViewContentOffsetDidChange:(NSDictionary *)change
......@@ -89,27 +94,55 @@
if (self.state != MJRefreshStateIdle) return;
if (_scrollView.panGestureRecognizer.state == UIGestureRecognizerStateEnded) {// 手松开
if (_scrollView.mj_insetT + _scrollView.mj_contentH <= _scrollView.mj_h) { // 不够一个屏幕
if (_scrollView.mj_offsetY >= - _scrollView.mj_insetT) { // 向上拽
[self beginRefreshing];
}
} else { // 超出一个屏幕
if (_scrollView.mj_offsetY >= _scrollView.mj_contentH + _scrollView.mj_insetB - _scrollView.mj_h) {
[self beginRefreshing];
UIGestureRecognizerState panState = _scrollView.panGestureRecognizer.state;
switch (panState) {
// 手松开
case UIGestureRecognizerStateEnded: {
if (_scrollView.mj_insetT + _scrollView.mj_contentH <= _scrollView.mj_h) { // 不够一个屏幕
if (_scrollView.mj_offsetY >= - _scrollView.mj_insetT) { // 向上拽
[self beginRefreshing];
}
} else { // 超出一个屏幕
if (_scrollView.mj_offsetY >= _scrollView.mj_contentH + _scrollView.mj_insetB - _scrollView.mj_h) {
[self beginRefreshing];
}
}
}// ‼️注意: 这里没有 break; fallthrough 执行重置 oneNewPan 语句 (Ended & Canceled & Failed)
case UIGestureRecognizerStateCancelled:
case UIGestureRecognizerStateFailed: {
self.oneNewPan = NO;
}
break;
case UIGestureRecognizerStateBegan: {
self.oneNewPan = YES;
}
break;
default:
break;
}
}
- (BOOL)ignoreRefreshAction {
return !self.isOneNewPan && self.isOnlyRefreshPerDrag;
}
- (void)beginRefreshing
{
if ([self ignoreRefreshAction]) return;
[super beginRefreshing];
}
- (void)setState:(MJRefreshState)state
{
MJRefreshCheckState
if (state == MJRefreshStateRefreshing) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self executeRefreshingCallback];
});
[self executeRefreshingCallback];
} else if (state == MJRefreshStateNoMoreData || state == MJRefreshStateIdle) {
if (MJRefreshStateRefreshing == oldState) {
if (self.endRefreshingCompletionBlock) {
......
......@@ -8,6 +8,10 @@
#import "MJRefreshFooter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MJRefreshBackFooter : MJRefreshFooter
@end
NS_ASSUME_NONNULL_END
......@@ -91,6 +91,9 @@
[UIView animateWithDuration:MJRefreshSlowAnimationDuration animations:^{
self.scrollView.mj_insetB -= self.lastBottomDelta;
if (self.endRefreshingAnimateCompletionBlock) {
self.endRefreshingAnimateCompletionBlock();
}
// 自动调整透明度
if (self.isAutomaticallyChangeAlpha) self.alpha = 0.0;
} completion:^(BOOL finished) {
......
......@@ -14,6 +14,8 @@
#import "UIScrollView+MJRefresh.h"
#import "NSBundle+MJRefresh.h"
NS_ASSUME_NONNULL_BEGIN
/** 刷新控件的状态 */
typedef NS_ENUM(NSInteger, MJRefreshState) {
/** 普通闲置状态 */
......@@ -31,7 +33,7 @@ typedef NS_ENUM(NSInteger, MJRefreshState) {
/** 进入刷新状态的回调 */
typedef void (^MJRefreshComponentRefreshingBlock)(void);
/** 开始刷新后的回调(进入刷新状态后的回调) */
typedef void (^MJRefreshComponentbeginRefreshingCompletionBlock)(void);
typedef void (^MJRefreshComponentBeginRefreshingCompletionBlock)(void);
/** 结束刷新后的回调 */
typedef void (^MJRefreshComponentEndRefreshingCompletionBlock)(void);
......@@ -45,7 +47,7 @@ typedef void (^MJRefreshComponentEndRefreshingCompletionBlock)(void);
}
#pragma mark - 刷新回调
/** 正在刷新的回调 */
@property (copy, nonatomic) MJRefreshComponentRefreshingBlock refreshingBlock;
@property (copy, nonatomic, nullable) MJRefreshComponentRefreshingBlock refreshingBlock;
/** 设置回调对象和回调方法 */
- (void)setRefreshingTarget:(id)target refreshingAction:(SEL)action;
......@@ -61,15 +63,17 @@ typedef void (^MJRefreshComponentEndRefreshingCompletionBlock)(void);
- (void)beginRefreshing;
- (void)beginRefreshingWithCompletionBlock:(void (^)(void))completionBlock;
/** 开始刷新后的回调(进入刷新状态后的回调) */
@property (copy, nonatomic) MJRefreshComponentbeginRefreshingCompletionBlock beginRefreshingCompletionBlock;
@property (copy, nonatomic, nullable) MJRefreshComponentBeginRefreshingCompletionBlock beginRefreshingCompletionBlock;
/** 带动画的结束刷新的回调 */
@property (copy, nonatomic, nullable) MJRefreshComponentEndRefreshingCompletionBlock endRefreshingAnimateCompletionBlock;
/** 结束刷新的回调 */
@property (copy, nonatomic) MJRefreshComponentEndRefreshingCompletionBlock endRefreshingCompletionBlock;
@property (copy, nonatomic, nullable) MJRefreshComponentEndRefreshingCompletionBlock endRefreshingCompletionBlock;
/** 结束刷新状态 */
- (void)endRefreshing;
- (void)endRefreshingWithCompletionBlock:(void (^)(void))completionBlock;
/** 是否正在刷新 */
@property (assign, nonatomic, readonly, getter=isRefreshing) BOOL refreshing;
//- (BOOL)isRefreshing;
/** 刷新状态 一般交给子类内部实现 */
@property (assign, nonatomic) MJRefreshState state;
......@@ -85,11 +89,11 @@ typedef void (^MJRefreshComponentEndRefreshingCompletionBlock)(void);
/** 摆放子控件frame */
- (void)placeSubviews NS_REQUIRES_SUPER;
/** 当scrollView的contentOffset发生改变的时候调用 */
- (void)scrollViewContentOffsetDidChange:(NSDictionary *)change NS_REQUIRES_SUPER;
- (void)scrollViewContentOffsetDidChange:(nullable NSDictionary *)change NS_REQUIRES_SUPER;
/** 当scrollView的contentSize发生改变的时候调用 */
- (void)scrollViewContentSizeDidChange:(NSDictionary *)change NS_REQUIRES_SUPER;
- (void)scrollViewContentSizeDidChange:(nullable NSDictionary *)change NS_REQUIRES_SUPER;
/** 当scrollView的拖拽状态发生改变的时候调用 */
- (void)scrollViewPanStateDidChange:(NSDictionary *)change NS_REQUIRES_SUPER;
- (void)scrollViewPanStateDidChange:(nullable NSDictionary *)change NS_REQUIRES_SUPER;
#pragma mark - 其他
......@@ -103,5 +107,8 @@ typedef void (^MJRefreshComponentEndRefreshingCompletionBlock)(void);
@interface UILabel(MJRefresh)
+ (instancetype)mj_label;
- (CGFloat)mj_textWith;
- (CGFloat)mj_textWidth;
@end
NS_ASSUME_NONNULL_END
......@@ -55,13 +55,14 @@
[self removeObservers];
if (newSuperview) { // 新的父控件
// 记录UIScrollView
_scrollView = (UIScrollView *)newSuperview;
// 设置宽度
self.mj_w = newSuperview.mj_w;
self.mj_w = _scrollView.mj_w;
// 设置位置
self.mj_x = -_scrollView.mj_insetL;
// 记录UIScrollView
_scrollView = (UIScrollView *)newSuperview;
// 设置永远支持垂直弹簧效果
_scrollView.alwaysBounceVertical = YES;
// 记录UIScrollView最开始的contentInset
......@@ -136,9 +137,7 @@
_state = state;
// 加入主队列的目的是等setState:方法调用完毕、设置完文字后再去布局子控件
dispatch_async(dispatch_get_main_queue(), ^{
[self setNeedsLayout];
});
MJRefreshDispatchAsyncOnMainQueue([self setNeedsLayout];)
}
#pragma mark 进入刷新状态
......@@ -171,9 +170,7 @@
#pragma mark 结束刷新状态
- (void)endRefreshing
{
dispatch_async(dispatch_get_main_queue(), ^{
self.state = MJRefreshStateIdle;
});
MJRefreshDispatchAsyncOnMainQueue(self.state = MJRefreshStateIdle;)
}
- (void)endRefreshingWithCompletionBlock:(void (^)(void))completionBlock
......@@ -228,7 +225,7 @@
#pragma mark - 内部方法
- (void)executeRefreshingCallback
{
dispatch_async(dispatch_get_main_queue(), ^{
MJRefreshDispatchAsyncOnMainQueue({
if (self.refreshingBlock) {
self.refreshingBlock();
}
......@@ -238,7 +235,7 @@
if (self.beginRefreshingCompletionBlock) {
self.beginRefreshingCompletionBlock();
}
});
})
}
@end
......@@ -254,22 +251,14 @@
return label;
}
- (CGFloat)mj_textWith {
- (CGFloat)mj_textWidth {
CGFloat stringWidth = 0;
CGSize size = CGSizeMake(MAXFLOAT, MAXFLOAT);
if (self.text.length > 0) {
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000
stringWidth =[self.text
boundingRectWithSize:size
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{NSFontAttributeName:self.font}
context:nil].size.width;
#else
stringWidth = [self.text sizeWithFont:self.font
constrainedToSize:size
lineBreakMode:NSLineBreakByCharWrapping].width;
#endif
stringWidth = [self.text boundingRectWithSize:size
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{NSFontAttributeName:self.font}
context:nil].size.width;
}
return stringWidth;
}
......
......@@ -9,6 +9,8 @@
#import "MJRefreshComponent.h"
NS_ASSUME_NONNULL_BEGIN
@interface MJRefreshFooter : MJRefreshComponent
/** 创建footer */
+ (instancetype)footerWithRefreshingBlock:(MJRefreshComponentRefreshingBlock)refreshingBlock;
......@@ -26,5 +28,7 @@
@property (assign, nonatomic) CGFloat ignoredScrollViewContentInsetBottom;
/** 自动根据有无数据来显示和隐藏(有数据就显示,没有数据隐藏。默认是NO) */
@property (assign, nonatomic, getter=isAutomaticallyHidden) BOOL automaticallyHidden;
@property (assign, nonatomic, getter=isAutomaticallyHidden) BOOL automaticallyHidden MJRefreshDeprecated("已废弃此属性,开发者请自行控制footer的显示和隐藏");
@end
NS_ASSUME_NONNULL_END
......@@ -38,31 +38,13 @@
self.mj_h = MJRefreshFooterHeight;
// 默认不会自动隐藏
self.automaticallyHidden = NO;
}
- (void)willMoveToSuperview:(UIView *)newSuperview
{
[super willMoveToSuperview:newSuperview];
if (newSuperview) {
// 监听scrollView数据的变化
if ([self.scrollView isKindOfClass:[UITableView class]] || [self.scrollView isKindOfClass:[UICollectionView class]]) {
[self.scrollView setMj_reloadDataBlock:^(NSInteger totalDataCount) {
if (self.isAutomaticallyHidden) {
self.hidden = (totalDataCount == 0);
}
}];
}
}
// self.automaticallyHidden = NO;
}
#pragma mark - 公共方法
- (void)endRefreshingWithNoMoreData
{
dispatch_async(dispatch_get_main_queue(), ^{
self.state = MJRefreshStateNoMoreData;
});
MJRefreshDispatchAsyncOnMainQueue(self.state = MJRefreshStateNoMoreData;)
}
- (void)noticeNoMoreData
......@@ -72,24 +54,11 @@
- (void)resetNoMoreData
{
dispatch_async(dispatch_get_main_queue(), ^{
self.state = MJRefreshStateIdle;
});
MJRefreshDispatchAsyncOnMainQueue(self.state = MJRefreshStateIdle;)
}
- (void)setAutomaticallyHidden:(BOOL)automaticallyHidden
{
_automaticallyHidden = automaticallyHidden;
if (automaticallyHidden) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[UITableView exchangeInstanceMethod1:@selector(reloadData) method2:@selector(mj_reloadData)];
[UICollectionView exchangeInstanceMethod1:@selector(reloadData) method2:@selector(mj_reloadData)];
});
#pragma clang diagnostic pop
}
}
@end
......@@ -9,6 +9,8 @@
#import "MJRefreshComponent.h"
NS_ASSUME_NONNULL_BEGIN
@interface MJRefreshHeader : MJRefreshComponent
/** 创建header */
+ (instancetype)headerWithRefreshingBlock:(MJRefreshComponentRefreshingBlock)refreshingBlock;
......@@ -18,8 +20,10 @@
/** 这个key用来存储上一次下拉刷新成功的时间 */
@property (copy, nonatomic) NSString *lastUpdatedTimeKey;
/** 上一次下拉刷新成功的时间 */
@property (strong, nonatomic, readonly) NSDate *lastUpdatedTime;
@property (strong, nonatomic, readonly, nullable) NSDate *lastUpdatedTime;
/** 忽略多少scrollView的contentInset的top */
@property (assign, nonatomic) CGFloat ignoredScrollViewContentInsetTop;
@end
NS_ASSUME_NONNULL_END
......@@ -48,25 +48,36 @@
self.mj_y = - self.mj_h - self.ignoredScrollViewContentInsetTop;
}
- (void)resetInset {
if (@available(iOS 11.0, *)) {
} else {
// 如果 iOS 10 及以下系统在刷新时, push 新的 VC, 等待刷新完成后回来, 会导致顶部 Insets.top 异常, 不能 resetInset, 检查一下这种特殊情况
if (!self.window) { return; }
}
// sectionheader停留解决
CGFloat insetT = - self.scrollView.mj_offsetY > _scrollViewOriginalInset.top ? - self.scrollView.mj_offsetY : _scrollViewOriginalInset.top;
insetT = insetT > self.mj_h + _scrollViewOriginalInset.top ? self.mj_h + _scrollViewOriginalInset.top : insetT;
self.insetTDelta = _scrollViewOriginalInset.top - insetT;
// 避免 CollectionView 在使用根据 Autolayout 和 内容自动伸缩 Cell, 刷新时导致的 Layout 异常渲染问题
if (self.scrollView.mj_insetT != insetT) {
self.scrollView.mj_insetT = insetT;
}
}
- (void)scrollViewContentOffsetDidChange:(NSDictionary *)change
{
[super scrollViewContentOffsetDidChange:change];
// 在刷新的refreshing状态
if (self.state == MJRefreshStateRefreshing) {
// if (self.window == nil) return;
// sectionheader停留解决
CGFloat insetT = - self.scrollView.mj_offsetY > _scrollViewOriginalInset.top ? - self.scrollView.mj_offsetY : _scrollViewOriginalInset.top;
insetT = insetT > self.mj_h + _scrollViewOriginalInset.top ? self.mj_h + _scrollViewOriginalInset.top : insetT;
self.scrollView.mj_insetT = insetT;
self.insetTDelta = _scrollViewOriginalInset.top - insetT;
[self resetInset];
return;
}
// 跳转到下一个控制器时,contentInset可能会变
_scrollViewOriginalInset = self.scrollView.mj_inset;
_scrollViewOriginalInset = self.scrollView.mj_inset;
// 当前的contentOffset
CGFloat offsetY = self.scrollView.mj_offsetY;
......@@ -114,6 +125,9 @@
[UIView animateWithDuration:MJRefreshSlowAnimationDuration animations:^{
self.scrollView.mj_insetT += self.insetTDelta;
if (self.endRefreshingAnimateCompletionBlock) {
self.endRefreshingAnimateCompletionBlock();
}
// 自动调整透明度
if (self.isAutomaticallyChangeAlpha) self.alpha = 0.0;
} completion:^(BOOL finished) {
......@@ -124,19 +138,21 @@
}
}];
} else if (state == MJRefreshStateRefreshing) {
dispatch_async(dispatch_get_main_queue(), ^{
MJRefreshDispatchAsyncOnMainQueue({
[UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{
CGFloat top = self.scrollViewOriginalInset.top + self.mj_h;
// 增加滚动区域top
self.scrollView.mj_insetT = top;
// 设置滚动位置
CGPoint offset = self.scrollView.contentOffset;
offset.y = -top;
[self.scrollView setContentOffset:offset animated:NO];
if (self.scrollView.panGestureRecognizer.state != UIGestureRecognizerStateCancelled) {
CGFloat top = self.scrollViewOriginalInset.top + self.mj_h;
// 增加滚动区域top
self.scrollView.mj_insetT = top;
// 设置滚动位置
CGPoint offset = self.scrollView.contentOffset;
offset.y = -top;
[self.scrollView setContentOffset:offset animated:NO];
}
} completion:^(BOOL finished) {
[self executeRefreshingCallback];
}];
});
})
}
}
......@@ -145,4 +161,11 @@
{
return [[NSUserDefaults standardUserDefaults] objectForKey:self.lastUpdatedTimeKey];
}
- (void)setIgnoredScrollViewContentInsetTop:(CGFloat)ignoredScrollViewContentInsetTop {
_ignoredScrollViewContentInsetTop = ignoredScrollViewContentInsetTop;
self.mj_y = - self.mj_h - _ignoredScrollViewContentInsetTop;
}
@end
......@@ -8,6 +8,8 @@
#import "MJRefreshAutoStateFooter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MJRefreshAutoGifFooter : MJRefreshAutoStateFooter
@property (weak, nonatomic, readonly) UIImageView *gifView;
......@@ -15,3 +17,5 @@
- (void)setImages:(NSArray *)images duration:(NSTimeInterval)duration forState:(MJRefreshState)state;
- (void)setImages:(NSArray *)images forState:(MJRefreshState)state;
@end
NS_ASSUME_NONNULL_END
......@@ -85,7 +85,7 @@
self.gifView.contentMode = UIViewContentModeCenter;
} else {
self.gifView.contentMode = UIViewContentModeRight;
self.gifView.mj_w = self.mj_w * 0.5 - self.labelLeftInset - self.stateLabel.mj_textWith * 0.5;
self.gifView.mj_w = self.mj_w * 0.5 - self.labelLeftInset - self.stateLabel.mj_textWidth * 0.5;
}
}
......
......@@ -8,7 +8,14 @@
#import "MJRefreshAutoStateFooter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MJRefreshAutoNormalFooter : MJRefreshAutoStateFooter
@property (weak, nonatomic, readonly) UIActivityIndicatorView *loadingView;
/** 菊花的样式 */
@property (assign, nonatomic) UIActivityIndicatorViewStyle activityIndicatorViewStyle;
@property (assign, nonatomic) UIActivityIndicatorViewStyle activityIndicatorViewStyle __attribute__((deprecated("first deprecated in 3.2.2 - Use `loadingView` property")));
@end
NS_ASSUME_NONNULL_END
......@@ -17,7 +17,7 @@
- (UIActivityIndicatorView *)loadingView
{
if (!_loadingView) {
UIActivityIndicatorView *loadingView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:self.activityIndicatorViewStyle];
UIActivityIndicatorView *loadingView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:_activityIndicatorViewStyle];
loadingView.hidesWhenStopped = YES;
[self addSubview:_loadingView = loadingView];
}
......@@ -28,6 +28,7 @@
{
_activityIndicatorViewStyle = activityIndicatorViewStyle;
[self.loadingView removeFromSuperview];
self.loadingView = nil;
[self setNeedsLayout];
}
......@@ -36,7 +37,14 @@
{
[super prepare];
self.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;
#if __IPHONE_OS_VERSION_MAX_ALLOWED > 130000
if (@available(iOS 13.0, *)) {
_activityIndicatorViewStyle = UIActivityIndicatorViewStyleMedium;
return;
}
#endif
_activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;
}
- (void)placeSubviews
......@@ -48,7 +56,7 @@
// 圈圈
CGFloat loadingCenterX = self.mj_w * 0.5;
if (!self.isRefreshingTitleHidden) {
loadingCenterX -= self.stateLabel.mj_textWith * 0.5 + self.labelLeftInset;
loadingCenterX -= self.stateLabel.mj_textWidth * 0.5 + self.labelLeftInset;
}
CGFloat loadingCenterY = self.mj_h * 0.5;
self.loadingView.center = CGPointMake(loadingCenterX, loadingCenterY);
......
......@@ -8,6 +8,8 @@
#import "MJRefreshAutoFooter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MJRefreshAutoStateFooter : MJRefreshAutoFooter
/** 文字距离圈圈、箭头的距离 */
@property (assign, nonatomic) CGFloat labelLeftInset;
......@@ -20,3 +22,5 @@
/** 隐藏刷新状态的文字 */
@property (assign, nonatomic, getter=isRefreshingTitleHidden) BOOL refreshingTitleHidden;
@end
NS_ASSUME_NONNULL_END
......@@ -15,6 +15,8 @@
}
/** 所有状态对应的文字 */
@property (strong, nonatomic) NSMutableDictionary *stateTitles;
/** 用于判断点击 Label 触发特殊的刷新逻辑 */
@property (assign, nonatomic) BOOL labelIsTrigger;
@end
@implementation MJRefreshAutoStateFooter
......@@ -43,11 +45,17 @@
self.stateLabel.text = self.stateTitles[@(self.state)];
}
- (BOOL)ignoreRefreshAction {
return !self.labelIsTrigger && [super ignoreRefreshAction];
}
#pragma mark - 私有方法
- (void)stateLabelClick
{
if (self.state == MJRefreshStateIdle) {
self.labelIsTrigger = YES;
[self beginRefreshing];
self.labelIsTrigger = NO;
}
}
......@@ -89,4 +97,4 @@
self.stateLabel.text = self.stateTitles[@(state)];
}
}
@end
\ No newline at end of file
@end
......@@ -8,6 +8,8 @@
#import "MJRefreshBackStateFooter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MJRefreshBackGifFooter : MJRefreshBackStateFooter
@property (weak, nonatomic, readonly) UIImageView *gifView;
......@@ -15,3 +17,5 @@
- (void)setImages:(NSArray *)images duration:(NSTimeInterval)duration forState:(MJRefreshState)state;
- (void)setImages:(NSArray *)images forState:(MJRefreshState)state;
@end
NS_ASSUME_NONNULL_END
......@@ -96,7 +96,7 @@
self.gifView.contentMode = UIViewContentModeCenter;
} else {
self.gifView.contentMode = UIViewContentModeRight;
self.gifView.mj_w = self.mj_w * 0.5 - self.labelLeftInset - self.stateLabel.mj_textWith * 0.5;
self.gifView.mj_w = self.mj_w * 0.5 - self.labelLeftInset - self.stateLabel.mj_textWidth * 0.5;
}
}
......
......@@ -8,8 +8,14 @@
#import "MJRefreshBackStateFooter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MJRefreshBackNormalFooter : MJRefreshBackStateFooter
@property (weak, nonatomic, readonly) UIImageView *arrowView;
@property (weak, nonatomic, readonly) UIActivityIndicatorView *loadingView;
/** 菊花的样式 */
@property (assign, nonatomic) UIActivityIndicatorViewStyle activityIndicatorViewStyle;
@property (assign, nonatomic) UIActivityIndicatorViewStyle activityIndicatorViewStyle __attribute__((deprecated("first deprecated in 3.2.2 - Use `loadingView` property")));
@end
NS_ASSUME_NONNULL_END
......@@ -31,7 +31,7 @@
- (UIActivityIndicatorView *)loadingView
{
if (!_loadingView) {
UIActivityIndicatorView *loadingView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:self.activityIndicatorViewStyle];
UIActivityIndicatorView *loadingView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:_activityIndicatorViewStyle];
loadingView.hidesWhenStopped = YES;
[self addSubview:_loadingView = loadingView];
}
......@@ -42,6 +42,7 @@
{
_activityIndicatorViewStyle = activityIndicatorViewStyle;
[self.loadingView removeFromSuperview];
self.loadingView = nil;
[self setNeedsLayout];
}
......@@ -50,7 +51,14 @@
{
[super prepare];
self.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;
#if __IPHONE_OS_VERSION_MAX_ALLOWED > 130000
if (@available(iOS 13.0, *)) {
_activityIndicatorViewStyle = UIActivityIndicatorViewStyleMedium;
return;
}
#endif
_activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;
}
- (void)placeSubviews
......@@ -60,7 +68,7 @@
// 箭头的中心点
CGFloat arrowCenterX = self.mj_w * 0.5;
if (!self.stateLabel.hidden) {
arrowCenterX -= self.labelLeftInset + self.stateLabel.mj_textWith * 0.5;
arrowCenterX -= self.labelLeftInset + self.stateLabel.mj_textWidth * 0.5;
}
CGFloat arrowCenterY = self.mj_h * 0.5;
CGPoint arrowCenter = CGPointMake(arrowCenterX, arrowCenterY);
......@@ -90,6 +98,9 @@
[UIView animateWithDuration:MJRefreshSlowAnimationDuration animations:^{
self.loadingView.alpha = 0.0;
} completion:^(BOOL finished) {
// 防止动画结束后,状态已经不是MJRefreshStateIdle
if (self.state != MJRefreshStateIdle) return;
self.loadingView.alpha = 1.0;
[self.loadingView stopAnimating];
......
......@@ -8,6 +8,8 @@
#import "MJRefreshBackFooter.h"
NS_ASSUME_NONNULL_BEGIN
@interface MJRefreshBackStateFooter : MJRefreshBackFooter
/** 文字距离圈圈、箭头的距离 */
@property (assign, nonatomic) CGFloat labelLeftInset;
......@@ -19,3 +21,5 @@
/** 获取state状态下的title */
- (NSString *)titleForState:(MJRefreshState)state;
@end
NS_ASSUME_NONNULL_END
......@@ -8,6 +8,8 @@
#import "MJRefreshStateHeader.h"
NS_ASSUME_NONNULL_BEGIN
@interface MJRefreshGifHeader : MJRefreshStateHeader
@property (weak, nonatomic, readonly) UIImageView *gifView;
......@@ -15,3 +17,5 @@
- (void)setImages:(NSArray *)images duration:(NSTimeInterval)duration forState:(MJRefreshState)state;
- (void)setImages:(NSArray *)images forState:(MJRefreshState)state;
@end
NS_ASSUME_NONNULL_END
......@@ -99,10 +99,10 @@
} else {
self.gifView.contentMode = UIViewContentModeRight;
CGFloat stateWidth = self.stateLabel.mj_textWith;
CGFloat stateWidth = self.stateLabel.mj_textWidth;
CGFloat timeWidth = 0.0;
if (!self.lastUpdatedTimeLabel.hidden) {
timeWidth = self.lastUpdatedTimeLabel.mj_textWith;
timeWidth = self.lastUpdatedTimeLabel.mj_textWidth;
}
CGFloat textWidth = MAX(stateWidth, timeWidth);
self.gifView.mj_w = self.mj_w * 0.5 - textWidth * 0.5 - self.labelLeftInset;
......
......@@ -8,8 +8,15 @@
#import "MJRefreshStateHeader.h"
NS_ASSUME_NONNULL_BEGIN
@interface MJRefreshNormalHeader : MJRefreshStateHeader
@property (weak, nonatomic, readonly) UIImageView *arrowView;
@property (weak, nonatomic, readonly) UIActivityIndicatorView *loadingView;
/** 菊花的样式 */
@property (assign, nonatomic) UIActivityIndicatorViewStyle activityIndicatorViewStyle;
@property (assign, nonatomic) UIActivityIndicatorViewStyle activityIndicatorViewStyle __attribute__((deprecated("first deprecated in 3.2.2 - Use `loadingView` property")));
@end
NS_ASSUME_NONNULL_END
......@@ -30,7 +30,7 @@
- (UIActivityIndicatorView *)loadingView
{
if (!_loadingView) {
UIActivityIndicatorView *loadingView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:self.activityIndicatorViewStyle];
UIActivityIndicatorView *loadingView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:_activityIndicatorViewStyle];
loadingView.hidesWhenStopped = YES;
[self addSubview:_loadingView = loadingView];
}
......@@ -42,6 +42,7 @@
{
_activityIndicatorViewStyle = activityIndicatorViewStyle;
[self.loadingView removeFromSuperview];
self.loadingView = nil;
[self setNeedsLayout];
}
......@@ -51,7 +52,14 @@
{
[super prepare];
self.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;
#if __IPHONE_OS_VERSION_MAX_ALLOWED > 130000
if (@available(iOS 13.0, *)) {
_activityIndicatorViewStyle = UIActivityIndicatorViewStyleMedium;
return;
}
#endif
_activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;
}
- (void)placeSubviews
......@@ -61,10 +69,10 @@
// 箭头的中心点
CGFloat arrowCenterX = self.mj_w * 0.5;
if (!self.stateLabel.hidden) {
CGFloat stateWidth = self.stateLabel.mj_textWith;
CGFloat stateWidth = self.stateLabel.mj_textWidth;
CGFloat timeWidth = 0.0;
if (!self.lastUpdatedTimeLabel.hidden) {
timeWidth = self.lastUpdatedTimeLabel.mj_textWith;
timeWidth = self.lastUpdatedTimeLabel.mj_textWidth;
}
CGFloat textWidth = MAX(stateWidth, timeWidth);
arrowCenterX -= textWidth / 2 + self.labelLeftInset;
......
......@@ -8,10 +8,12 @@
#import "MJRefreshHeader.h"
NS_ASSUME_NONNULL_BEGIN
@interface MJRefreshStateHeader : MJRefreshHeader
#pragma mark - 刷新时间相关
/** 利用这个block来决定显示的更新时间文字 */
@property (copy, nonatomic) NSString *(^lastUpdatedTimeText)(NSDate *lastUpdatedTime);
@property (copy, nonatomic, nullable) NSString *(^lastUpdatedTimeText)(NSDate *lastUpdatedTime);
/** 显示上一次刷新时间的label */
@property (weak, nonatomic, readonly) UILabel *lastUpdatedTimeLabel;
......@@ -23,3 +25,5 @@
/** 设置state状态下的文字 */
- (void)setTitle:(NSString *)title forState:(MJRefreshState)state;
@end
NS_ASSUME_NONNULL_END
......@@ -53,14 +53,6 @@
self.stateLabel.text = self.stateTitles[@(self.state)];
}
#pragma mark - 日历获取在9.x之后的系统使用currentCalendar会出异常。在8.0之后使用系统新API。
- (NSCalendar *)currentCalendar {
if ([NSCalendar respondsToSelector:@selector(calendarWithIdentifier:)]) {
return [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];
}
return [NSCalendar currentCalendar];
}
#pragma mark key的处理
- (void)setLastUpdatedTimeKey:(NSString *)lastUpdatedTimeKey
{
......@@ -79,8 +71,8 @@
if (lastUpdatedTime) {
// 1.获得年月日
NSCalendar *calendar = [self currentCalendar];
NSUInteger unitFlags = NSCalendarUnitYear| NSCalendarUnitMonth | NSCalendarUnitDay |NSCalendarUnitHour |NSCalendarUnitMinute;
NSCalendar *calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];
NSUInteger unitFlags = NSCalendarUnitYear| NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute;
NSDateComponents *cmp1 = [calendar components:unitFlags fromDate:lastUpdatedTime];
NSDateComponents *cmp2 = [calendar components:unitFlags fromDate:[NSDate date]];
......
B"MJRefreshHeaderIdleText" = "Pull down to refresh";
......
File mode changed from 100644 to 100755
//
// MJRefreshConfig.h
//
// Created by Frank on 2018/11/27.
// Copyright © 2018 小码哥. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface MJRefreshConfig : NSObject
/** 默认使用的语言版本, 默认为 nil. 将随系统的语言自动改变 */
@property (copy, nonatomic, nullable) NSString *languageCode;
/** @return Singleton Config instance */
+ (instancetype)defaultConfig;
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END
//
// MJRefreshConfig.m
//
// Created by Frank on 2018/11/27.
// Copyright © 2018 小码哥. All rights reserved.
//
#import "MJRefreshConfig.h"
@implementation MJRefreshConfig
static MJRefreshConfig *mj_RefreshConfig = nil;
+ (instancetype)defaultConfig {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
mj_RefreshConfig = [[self alloc] init];
});
return mj_RefreshConfig;
}
@end
......@@ -65,3 +65,11 @@ UIKIT_EXTERN NSString *const MJRefreshHeaderNoneLastDateText;
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} \
});
File mode changed from 100644 to 100755
......@@ -8,9 +8,13 @@
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSBundle (MJRefresh)
+ (instancetype)mj_refreshBundle;
+ (UIImage *)mj_arrowImage;
+ (NSString *)mj_localizedStringForKey:(NSString *)key value:(NSString *)value;
+ (NSString *)mj_localizedStringForKey:(NSString *)key value:(nullable NSString *)value;
+ (NSString *)mj_localizedStringForKey:(NSString *)key;
@end
NS_ASSUME_NONNULL_END
......@@ -8,6 +8,7 @@
#import "NSBundle+MJRefresh.h"
#import "MJRefreshComponent.h"
#import "MJRefreshConfig.h"
@implementation NSBundle (MJRefresh)
+ (instancetype)mj_refreshBundle
......@@ -24,7 +25,7 @@
{
static UIImage *arrowImage = nil;
if (arrowImage == nil) {
arrowImage = [[UIImage imageWithContentsOfFile:[[self mj_refreshBundle] pathForResource:@"gm_arrow@2x" ofType:@"png"]] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
arrowImage = [[UIImage imageWithContentsOfFile:[[self mj_refreshBundle] pathForResource:@"arrow@2x" ofType:@"png"]] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
}
return arrowImage;
}
......@@ -38,8 +39,13 @@
{
static NSBundle *bundle = nil;
if (bundle == nil) {
// (iOS获取的语言字符串比较不稳定)目前框架只处理en、zh-Hans、zh-Hant三种情况,其他按照系统默认处理
NSString *language = [NSLocale preferredLanguages].firstObject;
NSString *language = MJRefreshConfig.defaultConfig.languageCode;
// 如果配置中没有配置语言
if (!language) {
// (iOS获取的语言字符串比较不稳定)目前框架只处理en、zh-Hans、zh-Hant三种情况,其他按照系统默认处理
language = [NSLocale preferredLanguages].firstObject;
}
if ([language hasPrefix:@"en"]) {
language = @"en";
} else if ([language hasPrefix:@"zh"]) {
......@@ -48,6 +54,12 @@
} else { // zh-Hant\zh-HK\zh-TW
language = @"zh-Hant"; // 繁體中文
}
} else if ([language hasPrefix:@"ko"]) {
language = @"ko";
} else if ([language hasPrefix:@"ru"]) {
language = @"ru";
} else if ([language hasPrefix:@"uk"]) {
language = @"uk";
} else {
language = @"en";
}
......
......@@ -9,6 +9,8 @@
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIScrollView (MJExtension)
@property (readonly, nonatomic) UIEdgeInsets mj_inset;
......@@ -23,3 +25,5 @@
@property (assign, nonatomic) CGFloat mj_contentW;
@property (assign, nonatomic) CGFloat mj_contentH;
@end
NS_ASSUME_NONNULL_END
......@@ -10,17 +10,25 @@
#import "UIScrollView+MJExtension.h"
#import <objc/runtime.h>
#define SYSTEM_VERSION_GREATER_NOT_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
@implementation UIScrollView (MJExtension)
static BOOL respondsToAdjustedContentInset_;
+ (void)initialize
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
respondsToAdjustedContentInset_ = [self instancesRespondToSelector:@selector(adjustedContentInset)];
});
}
- (UIEdgeInsets)mj_inset
{
#ifdef __IPHONE_11_0
if (SYSTEM_VERSION_GREATER_NOT_LESS_THAN(@"11.0") && [self respondsToSelector:@selector(adjustedContentInset)]) {
if (respondsToAdjustedContentInset_) {
return self.adjustedContentInset;
}
#endif
......@@ -32,7 +40,7 @@
UIEdgeInsets inset = self.contentInset;
inset.top = mj_insetT;
#ifdef __IPHONE_11_0
if (SYSTEM_VERSION_GREATER_NOT_LESS_THAN(@"11.0") && [self respondsToSelector:@selector(adjustedContentInset)]) {
if (respondsToAdjustedContentInset_) {
inset.top -= (self.adjustedContentInset.top - self.contentInset.top);
}
#endif
......@@ -49,7 +57,7 @@
UIEdgeInsets inset = self.contentInset;
inset.bottom = mj_insetB;
#ifdef __IPHONE_11_0
if (SYSTEM_VERSION_GREATER_NOT_LESS_THAN(@"11.0") && [self respondsToSelector:@selector(adjustedContentInset)]) {
if (respondsToAdjustedContentInset_) {
inset.bottom -= (self.adjustedContentInset.bottom - self.contentInset.bottom);
}
#endif
......@@ -66,7 +74,7 @@
UIEdgeInsets inset = self.contentInset;
inset.left = mj_insetL;
#ifdef __IPHONE_11_0
if (SYSTEM_VERSION_GREATER_NOT_LESS_THAN(@"11.0") && [self respondsToSelector:@selector(adjustedContentInset)]) {
if (respondsToAdjustedContentInset_) {
inset.left -= (self.adjustedContentInset.left - self.contentInset.left);
}
#endif
......@@ -83,7 +91,7 @@
UIEdgeInsets inset = self.contentInset;
inset.right = mj_insetR;
#ifdef __IPHONE_11_0
if (SYSTEM_VERSION_GREATER_NOT_LESS_THAN(@"11.0") && [self respondsToSelector:@selector(adjustedContentInset)]) {
if (respondsToAdjustedContentInset_) {
inset.right -= (self.adjustedContentInset.right - self.contentInset.right);
}
#endif
......
......@@ -12,20 +12,19 @@
@class MJRefreshHeader, MJRefreshFooter;
@interface NSObject (MJRefresh)
+ (void)exchangeInstanceMethod1:(SEL)method1 method2:(SEL)method2;
+ (void)exchangeClassMethod1:(SEL)method1 method2:(SEL)method2;
@end
NS_ASSUME_NONNULL_BEGIN
@interface UIScrollView (MJRefresh)
/** 下拉刷新控件 */
@property (strong, nonatomic) MJRefreshHeader *mj_header;
@property (strong, nonatomic) MJRefreshHeader *header MJRefreshDeprecated("使用mj_header");
@property (strong, nonatomic, nullable) MJRefreshHeader *mj_header;
@property (strong, nonatomic, nullable) MJRefreshHeader *header MJRefreshDeprecated("使用mj_header");
/** 上拉刷新控件 */
@property (strong, nonatomic) MJRefreshFooter *mj_footer;
@property (strong, nonatomic) MJRefreshFooter *footer MJRefreshDeprecated("使用mj_footer");
@property (strong, nonatomic, nullable) MJRefreshFooter *mj_footer;
@property (strong, nonatomic, nullable) MJRefreshFooter *footer MJRefreshDeprecated("使用mj_footer");
#pragma mark - other
- (NSInteger)mj_totalDataCount;
@property (copy, nonatomic) void (^mj_reloadDataBlock)(NSInteger totalDataCount);
@end
NS_ASSUME_NONNULL_END
......@@ -12,20 +12,6 @@
#import "MJRefreshFooter.h"
#import <objc/runtime.h>
@implementation NSObject (MJRefresh)
+ (void)exchangeInstanceMethod1:(SEL)method1 method2:(SEL)method2
{
method_exchangeImplementations(class_getInstanceMethod(self, method1), class_getInstanceMethod(self, method2));
}
+ (void)exchangeClassMethod1:(SEL)method1 method2:(SEL)method2
{
method_exchangeImplementations(class_getClassMethod(self, method1), class_getClassMethod(self, method2));
}
@end
@implementation UIScrollView (MJRefresh)
#pragma mark - header
......@@ -38,10 +24,8 @@ static const char MJRefreshHeaderKey = '\0';
[self insertSubview:mj_header atIndex:0];
// 存储新的
[self willChangeValueForKey:@"mj_header"]; // KVO
objc_setAssociatedObject(self, &MJRefreshHeaderKey,
mj_header, OBJC_ASSOCIATION_ASSIGN);
[self didChangeValueForKey:@"mj_header"]; // KVO
mj_header, OBJC_ASSOCIATION_RETAIN);
}
}
......@@ -60,10 +44,8 @@ static const char MJRefreshFooterKey = '\0';
[self insertSubview:mj_footer atIndex:0];
// 存储新的
[self willChangeValueForKey:@"mj_footer"]; // KVO
objc_setAssociatedObject(self, &MJRefreshFooterKey,
mj_footer, OBJC_ASSOCIATION_ASSIGN);
[self didChangeValueForKey:@"mj_footer"]; // KVO
mj_footer, OBJC_ASSOCIATION_RETAIN);
}
}
......@@ -99,55 +81,18 @@ static const char MJRefreshFooterKey = '\0';
NSInteger totalCount = 0;
if ([self isKindOfClass:[UITableView class]]) {
UITableView *tableView = (UITableView *)self;
for (NSInteger section = 0; section<tableView.numberOfSections; section++) {
for (NSInteger section = 0; section < tableView.numberOfSections; section++) {
totalCount += [tableView numberOfRowsInSection:section];
}
} else if ([self isKindOfClass:[UICollectionView class]]) {
UICollectionView *collectionView = (UICollectionView *)self;
for (NSInteger section = 0; section<collectionView.numberOfSections; section++) {
for (NSInteger section = 0; section < collectionView.numberOfSections; section++) {
totalCount += [collectionView numberOfItemsInSection:section];
}
}
return totalCount;
}
static const char MJRefreshReloadDataBlockKey = '\0';
- (void)setMj_reloadDataBlock:(void (^)(NSInteger))mj_reloadDataBlock
{
[self willChangeValueForKey:@"mj_reloadDataBlock"]; // KVO
objc_setAssociatedObject(self, &MJRefreshReloadDataBlockKey, mj_reloadDataBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
[self didChangeValueForKey:@"mj_reloadDataBlock"]; // KVO
}
- (void (^)(NSInteger))mj_reloadDataBlock
{
return objc_getAssociatedObject(self, &MJRefreshReloadDataBlockKey);
}
- (void)executeReloadDataBlock
{
!self.mj_reloadDataBlock ? : self.mj_reloadDataBlock(self.mj_totalDataCount);
}
@end
@implementation UITableView (MJRefresh)
- (void)mj_reloadData
{
[self mj_reloadData];
[self executeReloadDataBlock];
}
@end
@implementation UICollectionView (MJRefresh)
- (void)mj_reloadData
{
[self mj_reloadData];
[self executeReloadDataBlock];
}
@end
......@@ -9,6 +9,8 @@
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIView (MJExtension)
@property (assign, nonatomic) CGFloat mj_x;
@property (assign, nonatomic) CGFloat mj_y;
......@@ -17,3 +19,5 @@
@property (assign, nonatomic) CGSize mj_size;
@property (assign, nonatomic) CGPoint mj_origin;
@end
NS_ASSUME_NONNULL_END
File mode changed from 100644 to 100755
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment