pragma mark copy和property
pragma mark 概念
/**
copy二个用途、一个引发问题
1.copy的第一个用途, 防止外界修改内部的数据
2.copy的第二个用途:__ 可以使用copy保存block, 这样可以保住 block中 使用的外界对象的命
3.copy block之后引发 循环引用 (你引用我,我引用你 双方都无法释放)
3.1 第三点出现的问题 需要对里面使用到的对象 添加一个 __block(意思是: 不要对block使用到该对象时, 进行一次retain操作)
__block 用处
1. 可以 在内部 修改 外部的值
2. 并且引用计数不会加1
*/
pragma mark 代码
#import <Foundation/Foundation.h>
#pragma mark 类
#import "Person.h"
#import "Dog.h"
#pragma mark main函数
int main(int argc, const char * argv[])
{
#pragma copy和property
#pragma mark 一.copy的第一个用途, 防止外界修改内部的数据
#warning 1.
NSMutableString *temp = [NSMutableString stringWithFormat:@"lyh"];
Person *p = [[Person alloc]init];
p.name = temp;
// 问题 : 修改了外面的变量, 影响到了 对象中的属性
[temp appendString:@" cool"];
NSLog(@"name = %@",p.name);
// 记住 : 以后字符串属性都用copy
NSLog(@"-----------1.end------------\n");
#warning 2.block 在内容修改 外部的值 (需要在 外部变量 添加 __block) [本质:block 默认存储在栈中 不会对外界的对象进行retain, 在堆才会]
// 调用block 想在内部里面修改 外部的值 加上__block
__block int num = 10;
// 1. 定义block
void (^myBlock) () = ^{
num = 20;
NSLog(@"%i",num);
};
// 2.调用block
myBlock();
// 3. block 默认存储在栈中, 栈中的block 访问到了外界的对象, 不会对 外界的对象的进行retain \
block 如果在堆中, 如果 在block中访问了外界的对象, 会对外界的对象 进行一次retain
NSLog(@"-----------2.end------------");
#warning 3.测试 将block 进行copy
Person *p1 = [[Person alloc]init];
NSLog(@"retainCount = %lu",[p retainCount]);
// 1. 定义block
void (^myBlock1) () = ^{
num = 20;
NSLog(@"%@",p);
NSLog(@"retainCount = %lu",[p retainCount]);
};
// myBlock1();
Block_copy(myBlock1); // 对block进行拷贝 // 将block转移到堆中
myBlock1();
NSLog(@"-----------3.end------------");
#pragma mark 二.copy的第二个用途:__ 可以使用copy保存block, 这样可以保住 block中 使用的外界对象的命
// 避免以后调用 block的时候, 外界的对象 已经释放了
#warning 4.
Dog *d = [[Dog alloc]init]; // 引用计算器 1
NSLog(@"d tainCount = %lu",[d retainCount]);
Person *p2 = [[Person alloc]init];
p2.pBlock = ^{
NSLog(@"%@",d); // 访问 这条狗
}; // 对block进行赋值
NSLog(@"d tainCount = %lu",[d retainCount]); // 2
#warning 这里的block不知道什么时候调用 但是狗有可能提前释放了(开启僵尸对象 可以查看内存)
// [Dog respondsToSelector:]
// 如果狗仔 调用block之前释放了, 那么程序就会崩溃
[d release]; // \
[block 为assgin] 引用计算器 0 \
[block 为copy 引用计算器 为 1]
p2.pBlock(); // 执行p的block \
[block 为assgin] 此处的狗的指针 是一个野指针 会崩溃 \
[block 为copy 需要在dealloc里面进行[block 进行release] 操作 --- Block_release(_pBlock); ]
[p2 release];
NSLog(@"-----------4.end------------");
#pragma mark 三. copy block之后引发 循环引用 (你引用我,我引用你 双方都无法释放)
#warning 5.
// 3. copy block之后引发 循环引用
// 如果 对象中的block 有 用到了对象自己, 为了避免内存泄露, 应该将对象 修饰为 __block (里面不会进行retain了)
__block Person *p3 =[[Person alloc]init]; // 1
NSLog(@"p3 tainCount = %lu",[p3 retainCount]);
p3.name = @"lyh";
p3.pBlock = ^{
NSLog(@"%@",p3.name); // 2
};
NSLog(@"p3 tainCount = %lu",[p3 retainCount]);
p3.pBlock();
[p3 release]; // 1
// [p3 release]; // 2B青年
return 0;
}
Person.h //人类
#import <Foundation/Foundation.h>
typedef void (^myBlock)();
@interface Person : NSObject
//@property(nonatomic, retain)NSString *name;
@property(nonatomic, copy)NSString *name;
// 注意: 如果block 使用 copy 并不是 拷贝, 而是从栈区 转移到 堆区
@property (nonatomic,copy)myBlock pBlock;
@end
Person.m
#import "Person.h"
@implementation Person
- (void)dealloc
{
// 只要 给 block 发送一条release消息, block中使用到的对象 也会收到该消息
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