看源代码时首先应该找到代码在github上的地址,基本上作者都会在github上的README上介绍使用的用法。
源码的地址为https://github.com/CoderMJLee/MJRefresh
,在readME中作者有列出整个代码的结构,如下图所示:
从上面的结构,我们可以看出,从刷新控件的基类MJRefreshComponent开始看起
1.看代码发现在交给子类方法去实现的方法后面都有添加一个宏NS_REQUIRES_SUPER,该宏的定义为:
define NS_REQUIRES_SUPER attribute((objc_requires_super))
_attribute((objc_requires_super))在2012年9月首次引入到CLANG中,并在2013年10月进行了介绍。在OS X和iOS上,现在都有一个NS_REQUIRES_SUPER宏,它根据编译器支持有条件地包装objc_requires_super属性。一旦方法声明附加了这个宏,编译器将会产生一个警告,如果super没有被覆盖该方法的子类调用。
这个宏可以有效的提醒我们忘记在子类中写
【super 父类方法】;
会弹出一个警告提醒我们。
2.在initWithFrame中调用了prepare方法
- (void)prepare
{
// 基本属性
self.autoresizingMask = UIViewAutoresizingFlexibleWidth;
self.backgroundColor = [UIColor clearColor];
}
这是为了适配不同大小的视图,使该刷新UIView和父视图左右的间距保持不变,相应的UIViewAutoresizing枚举类的各个含义如下:
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
//不会随父视图的改变而改变
UIViewAutoresizingNone = 0,
//自动调整view与父视图左边距,以保证右边距不变
UIViewAutoresizingFlexibleLeftMargin = 1 << 0,
//自动调整view的宽度,保证左边距和右边距不变
UIViewAutoresizingFlexibleWidth = 1 << 1,
//自动调整view与父视图右边距,以保证左边距不变
UIViewAutoresizingFlexibleRightMargin = 1 << 2,
//自动调整view与父视图上边距,以保证下边距不变
UIViewAutoresizingFlexibleTopMargin = 1 << 3,
//自动调整view的高度,以保证上边距和下边距不变
UIViewAutoresizingFlexibleHeight = 1 << 4,
//自动调整view与父视图的下边距,以保证上边距不变
UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};
之后,在layoutSubViews中调用方法
//默认布局,可以在子类中进行更改
[self placeSubViews];
之后重写了- (void)willMoveToSuperview:(UIView *)newSuperview方法,本身这个方法是不执行任何操作的,但是我们可以重写它添加一些我们想要的额外操作,该方法是父视图发生变化时调用。
在方法里面移除旧的UIScrollView的监听,给newSuperview添加新的监听
添加新的监听的方法为:
#pragma mark - KVO监听
//添加监听
- (void)addObservers
{
NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;
[self.scrollView addObserver:self forKeyPath:MJRefreshKeyPathContentOffset options:options context:nil];
[self.scrollView addObserver:self forKeyPath:MJRefreshKeyPathContentSize options:options context:nil];
//添加拖拽手势
self.pan = self.scrollView.panGestureRecognizer;
[self.pan addObserver:self forKeyPath:MJRefreshKeyPathPanState options:options context:nil];
}
//移除监听
- (void)removeObservers
{
[self.superview removeObserver:self forKeyPath:MJRefreshKeyPathContentOffset];
[self.superview removeObserver:self forKeyPath:MJRefreshKeyPathContentSize];
//移除拖拽手势
[self.pan removeObserver:self forKeyPath:MJRefreshKeyPathPanState];
self.pan = nil;
}
关于kvo的解释,可以参考这个作者的链接
https://www.jianshu.com/p/3bdc82e0ed4e
网友评论