oc82--成员变量使用copy修饰
//
// Person.h #import <Foundation/Foundation.h> typedef void (^myBlock)(); @interface Person : NSObject //@property (nonatomic, retain) NSString *name;
@property (nonatomic, copy) NSString *name; // 注意: 如果是block使用copy并不是拷贝, 将pBlock所指向的代码块从栈转移到堆中。block在堆中,使用外界对象的时候,会对外界对象的计数器加1,
@property (nonatomic, copy) myBlock pBlock;
//@property (nonatomic, retain) myBlock pBlock;
@end
//
// Person.m #import "Person.h" @implementation Person - (void)dealloc
{
// 由于block使用外界对象会对里面的对象加1,因此要在Person释放的时候把里面使用的对象也释放。
// 只要给block发送一条release消息, block中使用到的对象d也会收到该消息。
Block_release(_pBlock);
NSLog(@"%s", __func__);
[super dealloc];
}
@end
// Dog.h #import <Foundation/Foundation.h> @interface Dog : NSObject @end
// Dog.m #import "Dog.h" @implementation Dog - (void)dealloc
{
NSLog(@"%s", __func__);
[super dealloc];
}
@end
// main.m
// Copy与string,block的结合使用 #import <Foundation/Foundation.h>
#import "Person.h"
#import "Dog.h" int main(int argc, const char * argv[]) { // 1.copy的第一个用途, 防止外界修改内部的数据
NSMutableString *temp1 = [NSMutableString stringWithFormat:@"lnj"];
Person *p1 = [[Person alloc] init];
p1.name = temp1; //p1.name是一个新的对象,
// 问题: 修改了外面的变量, 影响到了对象中的属性,记住: 以后字符串属性都用copy
[temp1 appendString:@" cool"];
NSLog(@"name = %@", p1.name);//lnj __block int num = ;//block的本质是传了指针。才能修改外面的变量。
void (^myBlock1)() = ^{
num = ;
NSLog(@"%i", num);
};
myBlock1();// 20 // block默认存储在栈中, 栈中的block访问到了外界的对象, 不会对对象进行retain
// block如果在堆中, 如果在block中访问了外界的对象, 会对外界的对象进行一次retain
Person *p2 = [[Person alloc] init];
NSLog(@"retainCount = %lu", [p2 retainCount]);//
void (^myBlock)() = ^{
NSLog(@"%@", p2);
NSLog(@"retainCount = %lu", [p2 retainCount]);
};
myBlock();// retainCount = 1
Block_copy(myBlock); // 将block转移到堆中
myBlock();// retainCount = 2 // 2.可以使用copy保存block, 这样可以保住block中使用的外界对象的命
// 避免以后调用block的时候, 外界的对象已经释放了
/*__block*/ Dog *d = [[Dog alloc] init]; //
NSLog(@"Dog retainCount = %lu", [d retainCount]);//
Person *p3 = [[Person alloc] init];
p3.pBlock = ^{
//2,block在堆中,使用外界对象的时候,会对d的计数器加1,Dog前面加了__block,block里面使用dog也不会对dog加1,
NSLog(@"%@", d);
};
NSLog(@"Dog retainCount = %lu", [d retainCount]); // 2
// 如果狗在调用block之前释放了, 那么程序就会崩溃
[d release]; //
p3.pBlock();
[p3 release]; // 3.注意点: copy block之后引发循环引用。
// 如果对象中的block又用到了对象自己, 那么为了避免内存泄露, 应该将对象修饰为__block。
__block Person *p = [[Person alloc] init]; //
p.name = @"lnj";
NSLog(@"retainCount = %lu", [p retainCount]);
p.pBlock = ^{//由于是copy,所以这段代码在堆中,
NSLog(@"name = %@", p.name); // 2,由于内部用到了外部对象p,对p加1,所以p为2,所以p前面要加__block,block里面就不会对外部对象加1,
};
NSLog(@"retainCount = %lu", [p retainCount]); p.pBlock(); [p release]; // 1,p始终是1,无法释放。
[p release]; // 2B return ;
}
3的图片内存示意图

pBlock指向的是堆中的代码块地址。
oc82--成员变量使用copy修饰的更多相关文章
- java成员变量与局部变量修饰符的区别
成员变量: 可以被 public,static ,protected,default,final修饰. 局部变量:包括方法里的和 代码块里的(静态和非静态) 可以被default, final修饰 参 ...
- Objective-C 成员变量的访问修饰即成员变量可见性解析
总体来说Objective-C的访问成员变量可见性和C++基本一样,只是多了个@package. 以下是详细说明: 例子: @interface CTPerson : NSObject { @priv ...
- Java接口成员变量和方法默认修饰符
Java的interface中,成员变量的默认修饰符为:public static final 所以我们在interface中定义成员变量的时候,可以 1:public static final S ...
- java接口中成员变量和方法的默认修饰符(转)
Java的interface中,成员变量的默认修饰符为:public static final 所以我们在interface中定义成员变量的时候,可以 1:public static final St ...
- 【iOS 开发】Objective - C 面向对象 - 方法 | 成员变量 | 隐藏封装 | KVC | KVO | 初始化 | 多态
一. Objective-C 方法详解 1. 方法属性 (1) OC 方法传参机制 Object-C 方法传参机制 : OC 中得参数传递都是值传递, 传入参数的是参数的副本; -- 基本类型 (值传 ...
- Objective-C之成魔之路【9-类构造方法和成员变量作用域、以及变量】
郝萌主倾心贡献,尊重作者的劳动成果.请勿转载. 假设文章对您有所帮助,欢迎给作者捐赠,支持郝萌主,捐赠数额任意,重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载:点我传送 构造方法 ...
- java中的成员变量、静态变量与局部变量
java中的变量分为成员变量(又叫实例变量).静态变量和局部变量. 1.成员变量 1.1 成员变量(实例变量)是在类中定义的非static修饰的变量,可以不用赋初始值,不同的数据类型有默认的初始值. ...
- 匿名内部类访问方法成员变量需要加final的原因及证明(转)
https://blog.csdn.net/wjw521wjw521/article/details/77333820 在java编程中,没用的类定义太多对系统来说也是一个负担,这时候我们可以通过定义 ...
- Java成员变量和局部变量的区别
定义位置不同: 成员变量:类中方法外 分为类变量(static修饰).实例变量(没有使用static修饰) 局部变量:方法内.代码块内 默认值不同: 成员变量:有默认初始化值 局部变量:没有默认初始化 ...
随机推荐
- 关于Apache mod_rewrite的中文配置、使用和语法介绍(实现URL重写和防盗链功能)
以数据库后台驱动的动态内容的网站,经常会遇到这些的问题: 当在浏览器的地址栏输入一个无效的参数时,会出现数据库的错误提示,这是一个安全的隐患 搜索引擎无法收录你的所有网页 网页的链接地址是一系列的参数 ...
- 创建一个 Vue 的实例
每个 Vue 应用都是通过 Vue 函数创建一个新的 Vue 实例开始的: var vm = new Vue({ // 选项 }) 选项:el.data.methods el: 类型: ...
- Mybatis学习总结三(动态SQL)
通过mybatis提供的各种标签方法实现动态拼接sql. 一.if 和 where <select id="findUserList" parameterType=" ...
- 并发和多线程(二)--线程安全、synchronized、CAS简介
线程安全性: 当多个线程访问一个类的时候,这个类始终表示出正确的行为,那么这个类是线程安全的. 无状态的对象一定是线程安全的,例如大部分service.dao.Servlet都是无状态的. 线程安全体 ...
- 06Oracle Database 数据类型
Oracle Database 数据类型 字符型 char(n)最大2000个字节 定长 nchar(n)最大2000个字节 变长 varchar2(n) 最大4000个字节 变长 nvarchar2 ...
- Android studio开发-第一个应用
Android studio开发-第一个应用 上效果图 1.先创建布局文件 firstbutton.xml 代码 <?xml version="1.0" encoding=& ...
- 07Html、CSS
07Html.CSS-2018/07/17 1.HTML是用来描述网页的一种标记语言,是一套标记标签.HTML用使用标记标签来描述网页.超文本 标记语言. 2.格式 <html> < ...
- JavaScript--小白入门篇1
一.JavaScript简介 1.1 JavaScript的用途 JavaScript用来制作web页面交互效果,提升用户体验. 简单列出几个JavaScript能够制作的页面效果,它能干什 ...
- HDU-4705 Y(思维+dfs树)
Input 4 1 2 1 3 1 4 Output 1 题意:给你一颗树,选择一个三个点构成的集合,使得这三个点不在一条直线上(意思就是 从一个点出发,用一条不回头的线不能将这三个点连起来)问一共有 ...
- 第一章 Linux命令行简介
1 Linux系统命令操作语法的格式 命令_[参数选项]_[文件或路径] 其中 _ 至少一个空格 如:rm -f /etc/hosts 其中/etc/hosts完整路径不带空格 ...