情报局(1)
2017-01-13
- NSArray 用 copy 和 Strong修饰的区别
例如 self.a = b;
对于不可变对象来说使用copy,和Strong都可以。
copy的话对于setter方法,如果对方传进来的是b 不可变对象,那么copy之后a还是不可变对象,别的地方修改了b对a不会影响。
如果传进来的b是可变对象,那么copy之后a是不可变对象,修改b还是不会对a造成影响。
strong对于setter方法, 如果对方传进来的是b 不可变对象,那么copy之后a还是不可变对象,别的地方修改了b对a不会影响。
如果传进来的b是可变对象,那么copy之后a是不可变对象,修改b就会对a造成影响。
综上: 对于不可变对象应当使用copy修饰符
- NSMutable 用 copy 和 Strong修饰的区别
例如 self.a = b;
假设使用的是copy,无论传递进来的是什么,copy之后都会将a变成不可变对象。但是我们明明声名的是可变对象。这时候我们如果使用了 add, remove等方法时,就会抛出
unregonrized selector method for xx 经典错误。 因为我们声名的Mutable对象经过赋值之后就变成了imMutable对象。
综上: 对于可变对象应当使用 strong操作符
-
对NSArray及其子类做MutableCopy是深拷贝还是浅拷贝
首先补充 对于copy方法,无论源对象是可变还是不可变, 使用了copy生成的都是不可变对象,
对于MutableCopy方法,无论源对象是可变还是不可变, 使用了copy生成的都是不可变对象。
由于容器里面存的只是目标对象的指针,在做mutablecopy或者copy只是让容器变成是否可修改的,并不会修改容器内部指针所指向的内存地址。所以都是浅拷贝
2017-01-16
给出以下代码, 问 在block嵌套的时候是否需要 嵌套 weak strong dance?
@interface A : NSObject
@property (nonatomic, copy) dispatch_block_t block;
@end
@implementation A
- (void)dealloc {
NSLog(@"%@ dealloc ",[self class]);
}
@end
@interface B : NSObject
@property (nonatomic, copy) dispatch_block_t block;
@end
@implementation B
- (void)dealloc {
NSLog(@"%@ dealloc ",[self class]);
}
@end
#define weakify(A) __weak typeof((A)) A##__w = A;
#define strongify(A) __strong typeof((A)) A = A##__w ;
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// [self test1];
[self test2];
}
- (void)test1 {
A *a = [A new];
weakify(a)
a.block = ^{
strongify(a)
NSLog(@"%@",[a class]);
B *b = [B new];
b.block = ^{
NSLog(@"%@",[a class]);
};
};
a.block();
}
- (void)test2 {
A *a = [A new];
B *b = [B new];
weakify(b) weakify(a)
a.block = ^{
strongify(a) strongify(b)
NSLog(@"%@",[b class]);
NSLog(@"%@",[a class]);
b.block = ^{
NSLog(@"%@",[b class]);
NSLog(@"%@",[a class]);
};
};
a.block();
b.block();
}
@end
补充: #define weakify(A) weak typeof((A)) A##w = A;
这行宏语法是说明我声明一个weak的变量 名字为A__w ##在宏指令的作用是拼接
答: 具体需要看情况而定:很多人使用block的时候不去追究原理而是一味的死记硬背的记住要循环使用weak strong。
这里首先说明的是block只会捕获以下变量。 除了全局变量,block参数, block的内部变量 外的所有变量
。
并且,block持有这些变量的时机是在编译时期决定的,而不是运行时期。 所以只要block内只要出现了上述类型的变量就会去持有。
test1: a.block在内部出现了a这个外部变量,需要捕获a,为了避免出现循环引用我们是需要对a 使用weak strong 的,
在a.block()执行期间内部初始化了变量b 并且变量b.block捕获了a。a并没有捕获b,所以这时候出现的情况是 b.-> block -> a
a.block在执行完毕只会会释放变量b。随之释放.
test2: a.block内部出现了a,b的变量,但是此刻b并没有持有a,所以在外层block的时候只存在a->block-> (a,b) 并不存在 b->a,
所以为了避免循环引用,只需要对a使用weak strong。
在执行a.block的时候,在这个时刻,a->block->(a,b) (这是前提条件)。b.block持有了 a,b ,由于b->block->b,所以需要对b使用
weak strong,并且在此时刻 a->block->b 并且 b->block->a,出现了循环引用环,所以需要内部再出现一次 weak strong。
代码改写后为:
A *a = [A new];
B *b = [B new];
weakify(a)
a.block = ^{
strongify(a)
NSLog(@"%@",[b class]);
NSLog(@"%@",[a class]);
weakify(a) weakify(b)
b.block = ^{
strongify(a) strongify(b)
NSLog(@"%@",[b class]);
NSLog(@"%@",[a class]);
};
};
a.block();
b.block();
之前有人也提出问题说,我有时候也会用block关键字,这里我想说的是 block是说在捕获基本数据类型的时候捕获的是readonly(其实是一份副本)的值
如果我想修改这个值的话,使用__block关键字,这样在编译的时候传递进去的就是指针,和外部是一个值,
这里的问题是如何避免block捕获变量带来的内存泄漏的问题的分析。