iOS技术积累

不管生活有多不容易,都要守住自己的那一份优雅。

情报局(1)

2017-01-13

  1. 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修饰符

  1. NSMutable 用 copy 和 Strong修饰的区别
    例如 self.a = b;
    假设使用的是copy,无论传递进来的是什么,copy之后都会将a变成不可变对象。但是我们明明声名的是可变对象。这时候我们如果使用了 add, remove等方法时,就会抛出
    unregonrized selector method for xx 经典错误。 因为我们声名的Mutable对象经过赋值之后就变成了imMutable对象。

综上: 对于可变对象应当使用 strong操作符

  1. 对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捕获变量带来的内存泄漏的问题的分析。

评论卡