• iOS cop/assign /strong/weak


    1、OC中字符串为什么要用Copy

    在iOS开发中,我们在定义一个NSString的时候都会用copy来修饰,

    @property (nonatomic, copy)NSString *str;

    那为什么不用strong呢,我写了一个测试,来简单的说明一下

    首先把修饰符写成strong 

    在viewDidLoad的方法中,定义一个可变的字符串

    @property (nonatomic, strong)NSString *str;

    - (void)viewDidLoad {

    [super viewDidLoad];

    NSMutableString *string = [NSMutableString string];

    [string appendString:@"hello"];

    self.str = string;

    NSLog(@"%@",self.str);

    [string appendString:@"World"];

    NSLog(@"%@",self.str);

    }

    输出的结果是

    NSString中copy的问题[3807:239891] hello

    NSString中copy的问题[3807:239891] helloWorld

    我们只给self.str附了一次值,但是self.str 的值改变了,这是因为把可变字符的地址指向了str,所以string的值改变了,self.str也跟着改变,

    我们把strong改成copy以后

    @property (nonatomic, copy)NSString *str;

    输出的结果

     NSString中copy的问题[3852:242597] hello

     NSString中copy的问题[3852:242597] hello

    输出的结果显示,self.str的值只做了一次的修改,

    这样就能保证了在代码中,数据的安全

    2、iOS中weak和assign的区别

     assign和weak的区别

    大致的意思是说,weak比assign多了一个功能就是当属性所指向的对象消失的时候(也就是内存引用计数为0)会自动赋值为nil,这样再向weak修饰的属性发送消息就不会导致野指针操作crash。当assign指针所指向的内存被释放(释放并不等于抹除,只是引用计数为0),不会自动赋值nil,这样再引用self.assignPoint就会导致野指针操作,如果这个操作发生时内存还没有改变内容,依旧可以输出正确的结果,而如果发生时内存内容被改变了,就会crash。

     本质区别

     速度比较: __unsafe_unretained > __weak

    @property (nonatomic, assign) Test *test;  // 真实类型是 Test *__unsafe_unretained _test;

    __unsafe_unretained的特点:

    1.不是强引用, 不能保住OC对象的命

    2.如果引用的OC对象销毁了, 指针并不会被自动清空, 依然指向销毁的对象(很容易产生野指针错误: EXC_BAD_ACCESS)

    @property (nonatomic, weak) Test *test;  // Test * _Nullable __weak test;

    __weak的特点:

    1.不是强引用, 不能保住OC对象的命

    2.如果引用的OC对象销毁了, 指针会被自动清空(变为nil), 不再指向销毁的对象(永远不会产生野指针错误)

    - 用途

    - assign一般用在基本数据类型上面, 比如intdouble等

    - weak一般用在代理对象上面, 或者用来解决循环强引用的问题

    3、深拷贝(mutableCopy)和浅拷贝(copy):

    深拷贝就是内容拷贝,浅拷贝就是指针拷贝。

    copy vs retain

    retain和strong都是指针拷贝。当有其他对象引用当前对象时,会拷贝一份当前对象的地址,这样它就也指向当前对象了。所以,还是同一个对象,只是retainCount+1;

    copy:对于不可变对象copy采用的是浅复制,引用计数器加1(其实这是编译器进行了优化,既然原来的对象不可变,复制之后的对象也不可变那么就没有必要再重新创建一个对象了);对于可变对象copy采用的是深复制,引用计数器不变(原来的对象是可变,现在要产生一个不可变的当然得重新产生一个对象);

    浅复制如下:

    NSString *str1 = @"123";
    NSString *str2 = [str1 copy];4、xib跟storyboard拖得控件一般为 weak 而不是 strong

    4、xib跟storyboard拖的控件一般为weak而不是strong

    我们平时定义控件属性的时候一般都会用strong修饰符,而我们在用xib,sb拖控件的时候会发现,这时属性都是用的weak修饰符。

    1. 从storyboard或者xib上创建控件,在控件放在view上的时候,已经形成了如下的引用关系,以UIButton为例:
    UIViewController->UIView->subView->UIButton
    然后你为这个UIButton声明一个weak属性
    @property(nonatomic,weak) IBOOutlet UIButton *btn;
    
    相当于xib/sb对这个Button是强引用,你声明的属性对它是弱引用。

    2.手动创建控件
    a). 将控件声明成strong
    @property(nonatomic,strong) UIButton *btn;
    
    那么你在实现这个控件时只需这样:
    _btn = [[UIButton alloc]init];
    [self.view addSubview:_btn]
    

    b). 将控件声明成weak
    @property(nonatomic,weak) UIButton *btn;
    
    那么你在实现这个控件时需要这样:
    UIButton *button = [[UIButton alloc]init];
    _btn = button;
    [self.view addSubview:_btn];

    最近看的黑马iOS视频上给的建议的是:
    1.如果用Stroyboard拖线,用weak
    2.如果自定对象,用strong

    事实上IBOutlet的属性一般可以设为weak是因为它已经被view引用了,除非view被释放,否则IBOutlet的属性也不会被释放,另外IBOutlet属性的生命周期和view应该是一致的,所以IBOutlet属性一般设为weak。

    5、避免“强引用循环“的僵局:

      默认的引用方式是强引用,但上面说了有时我们还得使用弱引用,那是什么情况呢?

      答案,强引用循环:A对象强引用了B对象,B对象也强引用了A。因为都是强引用,也就是无论是A是B都要在对方的引用断了后才能销毁,但要断了引用,就必须对方对象销毁。就会出现这种僵局,为了避免出现这种情况,就应该有一个对象“示弱”,使其为“弱引用”。

      比较常见的,视图中的父子视图之间的引用:父视图强引用子视图,子视图弱引用父视图。

  • 相关阅读:
    flask的Request对象
    Spinner实现列表下拉功能
    ListView用法
    DatePickerDialog和TimePickerDialog(基于对话框显示时间和日期)
    DataPicker以及TimePicker显示时间和日期(屏幕上显示)
    Floyd-Warshall算法(最短路)
    Bellman-Ford算法(最短路)
    前向星
    css3变形与动画
    CSS3背景 background-size
  • 原文地址:https://www.cnblogs.com/dannygao/p/6958909.html
Copyright © 2020-2023  润新知