SVPullToRefresh
最近把項(xiàng)目里面的MJRefresh
換成了SVPullToRefresh
, 不得不說的是米奸,SVPullToRefresh
是我見過最好用最省事的一個(gè)刷新控件,添加上拉刷新和下拉加載就一句話。
添加上拉刷新
- (void)addPullToRefreshWithActionHandler:(void (^)(void))actionHandler;
添加下拉加載
- (void)addInfiniteScrollingWithActionHandler:(void (^)(void))actionHandler;
下面說說在用它的時(shí)候步绸,主要遇到的問題。
1.內(nèi)容本地化吃媒,在類UIScrollView+SVPullToRefresh.m
中瓤介,都是用的NSLocalizedString
顯示的提示語,例如赘那,pulltofresh...
,loading...
, 我們可以通過invoke - (void)setTitle:(NSString *)title forState:(SVPullToRefreshState)state;
這個(gè)函數(shù)刑桑,去改變它在不同的狀態(tài)顯示不同的中文,例如加載中...募舟, 下拉刷新..., 釋放即可更新, 其實(shí)大可不必這么麻煩祠斧, 不然在每個(gè)用到它的地方都需要寫上三句話,你需要做的就是創(chuàng)建一個(gè)Localizable.strings
的類拱礁,將用到的提示語進(jìn)行本地化琢锋,盡管你是用cocoapod 第三方導(dǎo)入的辕漂,這種方式依然是可以讓它 的內(nèi)容本地化。
2.在 UIViewControl
視圖中添加sv 刷新控件吴超,在viewDidload()
方法里面添加addpulltorefresh
钉嘹, 整個(gè)視圖會(huì)往上偏移64像素。解決方式:
: 1.如果是在viewDidload
中調(diào)用 addPullToRefreshWithActionHandler
方法鲸阻, 并且當(dāng)前的類繼承UITableViewControl
或者UICollectionViewControl
跋涣,可以設(shè)置self.tableView.contentInset = UIEdgeInsetsMake(64, 0, 0, 0);
,這樣設(shè)置后赘娄,解決了SVPullToRefresh
偏移像素的問題,并且導(dǎo)航欄還是透明的效果還是在的仆潮,因?yàn)榇藭r(shí)self.edgesForExtendedLayout
依舊是默認(rèn)的UIRectEdgeAll
(這里說的都是針對(duì)iOS 7+) ,所以self.tableview.frame
還是整個(gè)屏幕遣臼,包括了狀態(tài)欄和導(dǎo)航欄性置,所以現(xiàn)在的導(dǎo)航欄還會(huì)透明,就是這個(gè)原因了揍堰。
: 2.將當(dāng)前的self.edgesForExtendedLayout
設(shè)為UIRectEdgeNone
,也就是當(dāng)前的self.tableview.frame
是從導(dǎo)航欄下面開始算起的鹏浅,這時(shí)你的內(nèi)容根本都不會(huì)滑動(dòng)到導(dǎo)航欄下面去,就別說什么導(dǎo)航欄透明的效果了屏歹。
edgesForExtendedLayout
可以看看它的官方文檔季希。這種方式只是解決因?yàn)樘砑铀⑿驴丶淼钠茊栴},為了解決問題而解決問題幽纷。
探其究竟式塌,和正確的解決方式。
如果你當(dāng)前的視圖是UICollectionViewControl
或者UITableViewControl
友浸,在沒有添加addPull...
之前峰尝,整個(gè)視圖都是正常的,self.tableView
能顯示在正確的位置收恢,edgesForExtendedLayout
是默認(rèn)的UIRectEdgeAll
,一切正常武学,而自從你在viewDidLoad
里 面,添加了如下代碼
- (void)viewDidLoad {
[super viewDidLoad];
[self setupDataSource];
__weak SVViewController *weakSelf = self;
// setup pull-to-refresh
[self.tableView addPullToRefreshWithActionHandler:^{
[weakSelf insertRowAtTop];
}];
// setup infinite scrolling
[self.tableView addInfiniteScrollingWithActionHandler:^{
[weakSelf insertRowAtBottom];
}];
}
這時(shí)候的tableview
會(huì)出現(xiàn)偏移問題伦意,跑到SVPullToRefresh
源代碼中看究竟火窒,然后發(fā)現(xiàn) ,SVPullToRefreshView
的源點(diǎn)是以調(diào)用它的控件的源點(diǎn)設(shè)置的,
- (void)addPullToRefreshWithActionHandler:(void (^)(void))actionHandler position:(SVPullToRefreshPosition)position {
if(!self.pullToRefreshView) {
CGFloat yOrigin;
switch (position) {
case SVPullToRefreshPositionTop:
yOrigin = -SVPullToRefreshViewHeight;
break;
case SVPullToRefreshPositionBottom:
yOrigin = self.contentSize.height;
break;
default:
return;
}
SVPullToRefreshView *view = [[SVPullToRefreshView alloc] initWithFrame:CGRectMake(0, yOrigin, self.bounds.size.width, SVPullToRefreshViewHeight)];
view.pullToRefreshActionHandler = actionHandler;
view.scrollView = self;
[self addSubview:view];
//pulltorefreshView.originalTopInset` 用的是調(diào)用它視圖的contentInset.top
view.originalTopInset = self.contentInset.top;
view.originalBottomInset = self.contentInset.bottom;
view.position = position;
self.pullToRefreshView = view;
self.showsPullToRefresh = YES;
}
}
問題出現(xiàn)了驮肉,在viewDidload
里面沛鸵,self.tableView
或者是 self.collectionView
的contentInset
為(0,0,0,0); 而實(shí)際上是,如果是用的 UITableViewControl
,最后顯示的self.tableview
的contentOffset: {0, -64}
, 也就是說,其實(shí)是系統(tǒng)是會(huì)在再重設(shè)下self.tableView
的布局再去顯示的曲掰。而我們?cè)?code>viewDidload 時(shí)去添加刷新控件,而這時(shí)的tableview
的布局并沒有完全的確定奈辰,所以會(huì)往上偏移栏妖。所以解決這類問題最好的方法也就是,等視圖上控件的 frame
完全被設(shè)置好后奖恰,再去添加SVPullToRefresh
控件吊趾,換言之,我們只需要將viewDidload()
里面添加的刷新方法移到 viewDidLayoutSubviews
中瑟啃,這時(shí)的tableView frame
已被設(shè)置好论泛,自然控件的地方也會(huì)顯示對(duì)。
- (void)viewDidLayoutSubviews {
if (self.tableView.pullToRefreshView == nil) {
[self.tableView addPullToRefreshWithActionHandler:^{
}];
}
}
最后, 以UITableViewContro
為例蛹屿,看看它 的生命周期屁奏,以及tableView
frame
和contentInset
的變化,并更加深層次的促進(jìn)對(duì)viewcontrol
的生命周期的認(rèn)識(shí)
2015-10-30 00:27:48.699 LifeCycle[1197:84273] viewDidLoad = <UITableView: 0x7fa9e5898000; frame = (0 0; 414 736); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x7fa9e3fd3c10>; layer = <CALayer: 0x7fa9e3f7d730>; contentOffset: {0, 0}; contentSize: {600, 0}>
2015-10-30 00:27:48.720 LifeCycle[1197:84273] viewWillAppear = <UITableView: 0x7fa9e5898000; frame = (0 0; 414 736); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x7fa9e3fd3c10>; layer = <CALayer: 0x7fa9e3f7d730>; contentOffset: {0, -64}; contentSize: {600, 0}>
2015-10-30 00:27:48.733 LifeCycle[1197:84273] viewWillLayoutSubviews = <UITableView: 0x7fa9e5898000; frame = (0 0; 414 736); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x7fa9e3fd3c10>; layer = <CALayer: 0x7fa9e3f7d730>; contentOffset: {0, -64}; contentSize: {414, 0}>
2015-10-30 00:27:48.778 LifeCycle[1197:84273] viewDidLayoutSubviews = <UITableView: 0x7fa9e5898000; frame = (0 0; 414 736); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x7fa9e3fd3c10>; layer = <CALayer: 0x7fa9e3f7d730>; contentOffset: {0, -64}; contentSize: {414, 0}>
2015-10-30 00:27:48.779 LifeCycle[1197:84273] viewWillLayoutSubviews = <UITableView: 0x7fa9e5898000; frame = (0 0; 414 736); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x7fa9e3fd3c10>; layer = <CALayer: 0x7fa9e3f7d730>; contentOffset: {0, -64}; contentSize: {414, 0}>
2015-10-30 00:27:48.824 LifeCycle[1197:84273] viewDidLayoutSubviews = <UITableView: 0x7fa9e5898000; frame = (0 0; 414 736); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x7fa9e3fd3c10>; layer = <CALayer: 0x7fa9e3f7d730>; contentOffset: {0, -64}; contentSize: {414, 0}>
2015-10-30 00:27:48.831 LifeCycle[1197:84273] viewDidAppear = <UITableView: 0x7fa9e5898000; frame = (0 0; 414 736); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x7fa9e3fd3c10>; layer = <CALayer: 0x7fa9e3f7d730>; contentOffset: {0, -64}; contentSize: {414, 0}>
從上面错负,并不難看出坟瓢,在viewWillLayoutSubviews
方法中, 系統(tǒng)對(duì)tableView
的contentOffset
和contentSize
進(jìn)行了調(diào)整犹撒。所以折联,一般用到tableView
布局關(guān)系的,最好是在它布局穩(wěn)定下后再去進(jìn)行調(diào)整或添加识颊。
再后來項(xiàng)目中發(fā)現(xiàn)诚镰,使用SVPullToRefresh 會(huì)在iOS 7 上crash, 經(jīng)過層層調(diào)試祥款,最后解決方法竟然需要改sv 的源代碼清笨,添加