1.MJRefresh(主要封裝了六種刷新控件)
類 | 作用 |
---|---|
MJRefreshComponent | 繼承自UIView 朦乏,最基本的刷新類 |
MJRefreshHeader | 最基本的下拉刷新類 |
MJRefreshStateHeader | 可以下拉刷新黔夭,但是只有文字 |
MJRefreshNormalHeader | 默認(rèn)的刷新樣式氧卧,有文字,有上下箭頭初橘,有菊花 |
主要使用以下幾個(gè)
- MJRefreshNormalHeader
- MJRefreshGifHeader
- MJRefreshBackNormalFooter
- MJRefreshBackGifFooter
- MJRefreshAutoNormalFooter
- MJRefreshAutoGIfFooter
2.MJ 刷新block造成veiwcontroller內(nèi)存不釋放問(wèn)題
? self的成員變量Tableview.mj_header 引用了刷新方法的block,block引用了self的函數(shù)轧坎,同時(shí)還引用了成員變量Tableview.mj_header 股耽,造成了兩個(gè)循環(huán)引用,導(dǎo)致了viewcontroller不釋放褐健。
- 以下是引起循環(huán)引用的代碼:
_tableV1.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
[_tableV1.mj_header beginRefreshing];
//request
[self removeAllTableAry];
[self refreshRequest];
[_tableV1.mj_header endRefreshing];
}];
- 而當(dāng)使用target方法時(shí)并不會(huì)產(chǎn)生循環(huán)引用這個(gè)問(wèn)題付鹿。
_tableV1.mj_header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(refreshRequest)];
_tableV1.mj_footer = [MJRefreshBackNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadTableV1MoreData)];
- 打破MJ方法中的block循環(huán)引用如下:
__weak typeof(self) weakSelf = self;
__weak typeof(_tableV1.mj_header) weakHeader = _tableV1.mj_header;
_tableV1.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
typeof (weakSelf)strongSelf = weakSelf;
typeof (weakHeader)strongHeader = weakHeader;
[strongHeader beginRefreshing];
//request
[strongSelf refreshRequest];
[strongHeader endRefreshing];
}];
3.討論下關(guān)于block循環(huán)引用的問(wèn)題
//情況一:
- (void)case1 {
? NSLog(@"case 1 Click");
? dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
? self.name = @"case 1";
? });
? }
//情況二
- (void)case2 {
? NSLog(@"case 2 Click");
? __weak typeof(self) weakSelf = self;
? [self.teacher requestData:^(NSData *data) {
? typeof(weakSelf) strongSelf = weakSelf;
? strongSelf.name = @"case 2";
? }];
? }
//情況三
? - (void)case3 {
? NSLog(@"case 3 Click");
? [self.teacher requestData:^(NSData *data) {
? self.name = @"case 3";
? }];
? }
//情況四
? - (void)case4 {
? NSLog(@"case 4 Click");
? [self.teacher requestData:^(NSData *data) {
? self.name = @"case 4";
? self.teacher = nil;
? }];
? }
//情況五
? - (void)case5 {
? NSLog(@"case 5 Click");
? Teacher *t = [[Teacher alloc] init];
? [t requestData:^(NSData *data) {
? self.name = @"case 5";
? }];
? }
//情況六
? - (void)case6 {
? NSLog(@"case 6 Click");
? [self.teacher callCase6BlackEvent];
? self.teacher.case6Block = ^(NSData *data) {
? self.name = @"case 6";
? //下面兩句代碼任選其一
? self.teacher = nil;
? // self.teacher.case6Block = nil;
? };
? }
分析
- 情況一:執(zhí)行了dealloc,不泄露蚜迅,此情況雖然是block舵匾,但未形成保留環(huán)block -> self
- 情況二:執(zhí)行了dealloc,不泄露谁不,此情況就是內(nèi)存泄漏后的一般處理了 self ->teacher ->block ->strongSelf坐梯,后面那個(gè)strongSelf和原來(lái)的self并沒(méi)有直接關(guān)系,因?yàn)閟trongSelf是通過(guò)weakSelf得來(lái)的刹帕,而weakSelf又沒(méi)有強(qiáng)引用原來(lái)的self
- 情況三:未執(zhí)行dealloc吵血,內(nèi)存泄漏,此情況就是最典型的循環(huán)引用了偷溺,形成保留環(huán)無(wú)法釋放蹋辅,self ->teacher ->block ->self
- 情況四:執(zhí)行了dealloc,不泄露亡蓉,雖然也是保留環(huán)晕翠,但通過(guò)最后一句,使self不再?gòu)?qiáng)引用teacher,打破了保留環(huán)
- 情況五:執(zhí)行了dealloc淋肾,不泄露硫麻,未形成保留環(huán) t ->block ->self
- 情況六:執(zhí)行了dealloc,不泄露樊卓,最后兩句代碼任選其一即可防止內(nèi)存泄漏拿愧,self.teacher 或者 case6Block 置為空都可以打破 retain cycle
PS: 雖然情況四、情況六的寫(xiě)法都可以防止內(nèi)存泄漏碌尔,不過(guò)為了統(tǒng)一浇辜,個(gè)人建議最好還是按照普通寫(xiě)法即情況二的寫(xiě)法。