Block 访问成员变量

答案是肯定会造成强引用,和属性变量一样的结果,只不过比较隐形;

解决方案有很多:1、把成员变量改成属性,通过weakSelf调;2、(也是苹果文档里说的)声明一个局部变量接一下_block 来修饰,在block里用这个局部变量;

 __weak typeof(self)weakSelf = self;

_block NSString *local_about = _about;

 item.cellSelectBlock = ^(NSIndexPath *path){

               ProtocolHTMLController *htmlVC = [[ProtocolHTMLController alloc]init];

              htmlVC.requesURL = local_about;  // 使用

              [weakSelf.navigationController pushViewController:htmlVC animated:YES];

};
 

案例如下:

问题

ViewController 中定义成员变量如下:

 

@implementation EHISalesLeadsListViewController {
     __block NSString *pageNum;
}

使用如下:

 

    self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
        pageNum = @"1";
    }];

在这里,该 ViewController 消失时并没有走 dealloc 释放。

 

成员变量和属性都是 self 引用的变量。

成员变量:一般直接使用,不需要使用 self 引用(也可以使用 self-> 引用);
属性:一般都使用 self. 引用(也可以使用下划线 _ );

所以在 Block 中,属性一般会保持习惯使用 self. 引用,而成员变量容易忘记使用 self-> 引用。

在上面,因为 self 强引用 tableViewtableView 强引用 BlockBlock 内使用 self 的成员变量 pageNum。鉴于上面这句话,因此代码中虽然没有写 self-> 引用,也会已经强引用 self 了。因为都是强引用,三者形成循环引用,内存泄露。

所以,我们要打破循环引用。

2.1 weakSelf

打破循环引用要使其中一方为 weak 弱引用,通常我们会在 Block 外先把 self weak 掉,再在内部使用,如下:

 

    @weakify(self)
    self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
        @strongify(self)
        self->pageNum = @"1";
    }];

2.2 声明__block 修饰

可以使用 __weak 指向成员变量解决循环引用,也可以使用 __block 来解决。因为这里要修改变量的值,所以只能使用 __block

 

__block NSInteger blockPageIndex = pageIndex;
self.tableView.mj_footer = [MJRefreshBackNormalFooter footerWithRefreshingBlock:^{
    blockPageIndex ++;
}];

3. 成员变量是否声明 __block 并没有影响

 

@implementation EHISalesLeadsListViewController {
     __block NSString *pageNum;
}

前面在声明成员变量的时候使用 __block 修饰了,经过试验,完全没有作用,没有影响。


 

 

 

### Java 中局部变量与成员变量的区别及使用场景 #### 1. 定义位置 成员变量定义在类内部,但在方法外部。它们属于类的一部分,并且可以通过对象访问[^2]。 局部变量则定义在方法内部、构造器中或代码块中,其作用域仅限于所在的方法或代码块内[^4]。 #### 2. 存储位置 成员变量存储在堆内存中,随对象的创建而存在,并在其所属对象销毁时释放。对于静态成员变量,则存储在 JVM 的方法区中[^1]。 局部变量存储在栈内存中,随着方法的调用而创建,并在方法执行完毕后自动清除[^2]。 #### 3. 生命周期 成员变量的生命周期与其所属对象一致。一旦对象被垃圾回收机制清理,成员变量也随之消失。如果是静态成员变量,则从类加载到卸载期间一直存在。 局部变量的生命周期较短,仅存在于方法或代码块被执行的过程中。方法结束后,局部变量立即失去作用并被移除[^2]。 #### 4. 初始化方式 成员变量会被系统自动初始化,默认值取决于数据类型(如 `int` 默认为 `0`,`boolean` 默认为 `false` 等)。即使未显式赋值,也可以安全地读取这些默认值[^4]。 局部变量不会获得默认值,必须在使用前显式初始化。否则编译器会报错提示“可能尚未初始化”[^4]。 #### 5. 使用场景 - **成员变量**适用于保存对象的状态信息或共享的数据。例如,一个学生对象可能会有一个名为 `name` 的成员变量用于记录学生的姓名[^4]。 - **局部变量**主要用于临时存储计算过程中的中间结果或其他短暂使用的数据。由于其作用域有限,能够减少不必要的资源占用和潜在冲突[^4]。 #### 示例代码 以下是一个综合示例展示了成员变量与局部变量的应用差异: ```java public class VariableExample { // 成员变量 private String memberVariable; public void setMemberVariable(String value) { this.memberVariable = value; } public String getMemberVariable() { return memberVariable; } public void demonstrateLocalVariables() { // 局部变量 int localVar = 10; if (localVar > 5) { int anotherLocalVar = 20; // 块级局部变量 System.out.println("Block-level local variable: " + anotherLocalVar); } // 下面这一行会导致编译错误,因为anotherLocalVar超出了作用域 // System.out.println(anotherLocalVar); System.out.println("Method-local variable: " + localVar); } public static void main(String[] args) { VariableExample example = new VariableExample(); example.setMemberVariable("This is a member variable"); System.out.println(example.getMemberVariable()); example.demonstrateLocalVariables(); } } ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值