Some MJ Refresh pits

Posted by besly98 on Sun, 02 Jun 2019 00:02:44 +0200

1. MJRefresh (mainly encapsulated six refresh controls)


MJ framework diagram
class Effect
MJRefreshComponent Inherited from UIView, the most basic refresh class
MJRefreshHeader The most basic drop-down refresh class
MJRefreshStateHeader You can drop-down refresh, but only text
MJRefreshNormalHeader Default refresh style, with text, up and down arrows, Chrysanthemum

Mainly use the following

  • MJRefreshNormalHeader
  • MJRefreshGifHeader
  • MJRefreshBackNormalFooter
  • MJRefreshBackGifFooter
  • MJRefreshAutoNormalFooter
  • MJRefreshAutoGIfFooter

2.MJ refresh block causes memory unrelease problem of veiwcontroller

The member variable Tableview.mj_header of self refers to the block of the refresh method, the block refers to the function of self, and the member variable Tableview.mj_header is also referred to, resulting in two circular references, which results in the viewcontroller not releasing.

  • The following is the code that causes a circular reference:
_tableV1.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
    [_tableV1.mj_header beginRefreshing];
    //request
    [self removeAllTableAry];
    [self refreshRequest];
    [_tableV1.mj_header endRefreshing];
}];
  • The problem of circular references does not arise when the target method is used.
_tableV1.mj_header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(refreshRequest)];

_tableV1.mj_footer = [MJRefreshBackNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadTableV1MoreData)];   
  • Break the block loop reference in the MJ method as follows:
__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. Discuss the following questions about block circular reference

//Situation 1:

- (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";

​ });

​ }

//Situation two

- (void)case2 {

​ NSLog(@"case 2 Click");

​ __weak typeof(self) weakSelf = self;

​ [self.teacher requestData:^(NSData *data) {

​ typeof(weakSelf) strongSelf = weakSelf;

strongSelf.name = @"case 2";

​ }];

​ }

//Situation three

​ - (void)case3 {

​ NSLog(@"case 3 Click");

​ [self.teacher requestData:^(NSData *data) {

self.name = @"case 3";

​ }];

​ }

//Situation four

​ - (void)case4 {

​ NSLog(@"case 4 Click");

​ [self.teacher requestData:^(NSData *data) {

self.name = @"case 4";

​ self.teacher = nil;

​ }];

​ }

//Situation five

​ - (void)case5 {

​ NSLog(@"case 5 Click");

​ Teacher *t = [[Teacher alloc] init];

​ [t requestData:^(NSData *data) {

self.name = @"case 5";

​ }];

​ }

//Situation six

​ - (void)case6 {

​ NSLog(@"case 6 Click");

​ [self.teacher callCase6BlackEvent];

​ self.teacher.case6Block = ^(NSData *data) {

self.name = @"case 6";

​ //Choose one of the following two lines of code

​ self.teacher = nil;

​ // self.teacher.case6Block = nil;

​ };

​ }

Analysis

  • Case 1: Dealoc is executed without leakage. Although this case is block, it does not form a reserved ring block - > self
  • Case 2: Dealoc is executed without leakage. This situation is that after memory leak, self - > teacher - > block - > strong Self is generally handled. The latter strong Self is not directly related to the original self, because strong Self is obtained through weak Self, while weak Self does not strongly refer to the original self.
  • Case 3: Dealoc is not executed and memory leaks occur. This is the most typical case of circular reference. The formation of a retaining ring can not be released. Self-> teacher-> block-> self
  • Situation 4: Dealoc is executed, not leaking, although it is also a retaining ring, but through the last sentence, self no longer strongly quotes teacher, breaking the retaining ring
  • Case 5: Dealoc is executed, no leaks are made and no reserved ring t->block->self is formed.
  • Case 6: Dealoc is executed without leaking. One of the last two sentences of code can prevent memory leaks. Holding self.teacher or case6Block empty can break the retain cycle.

PS: Although the writing of case 4 and case 6 can prevent memory leaks, for the sake of uniformity, I suggest that it is better to follow the common writing of case 2.