NSString NSMutableString copy mutableCopy retain weak strong

  • NSString 与 NSMutableString

NSString是不可变字符串对象,这句话的意思,结合代码:

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {

        NSString *str = @"Shaw";
        NSString *str1 = @"Root";   // NSString *str1的意思是str1指向的@"Root"对象是不可变的,但str1是可以改变指向的。
        NSLog(@"str = %@, str1 = %@",str,str1);
        NSLog(@"str:%p, str1:%p",str,str1);
        str = [str stringByAppendingString:@"andRoot"];  // 打印可以看到str地址变了,因为原地址下的对象是不可变的。
        NSLog(@"str:%p, str1:%p",str,str1);
        str1 = str;  // 使str1指向str对象
        NSLog(@"str = %@, str1 = %@",str,str1);
        NSLog(@"str:%p, str1:%p",str,str1);

    }
    return 0;
}// 输出结果
2016-04-06 13:32:45.320 test[40011:4790098] str = Shaw, str1 = Root
2016-04-06 13:32:45.321 test[40011:4790098] str:0x100001050, str1:0x100001070
2016-04-06 13:32:45.321 test[40011:4790098] str:0x1001026b0, str1:0x100001070
2016-04-06 13:32:45.321 test[40011:4790098] str = ShawandRoot, str1 = ShawandRoot
2016-04-06 13:32:45.321 test[40011:4790098] str:0x1001026b0, str1:0x1001026b0
Program ended with exit code: 0

同理,NSMutableString就是可变字符串对象。

stringByAppendingString:方法的定义为:- (NSString *)stringByAppendingString:(NSString *)aString;

        NSMutableString *mStr = [NSMutableString stringWithString:@"Shaw"];
        NSLog(@"%@ %p",mStr,mStr);
        [mStr appendString:@"andRoot"]; //  可以看到输出地址为同一个,即对当前对象做了改变。
        NSLog(@"%@ %p",mStr,mStr);

// 输出结果
2016-04-06 16:17:05.789 test[40118:4806417] Shaw 0x100203470
2016-04-06 16:17:05.790 test[40118:4806417] ShawandRoot 0x100203470
Program ended with exit code: 0

如果用NSMutableString对象调用stringByAppendingString:方法会出现警告"Incompatible pointer types assigning NSMutableString to NSString"


  • mutableCopy 与 copy

有如下的结果:

复制不可变对象时

1. copy是浅复制,即指针复制,两个指针都指向那块空间

2. mutableCopy是深复制,即新开辟一块空间,将对象复制过去

复制可变对象时

mutableCopy与copy都是深复制,但copy返回的对象不可变

下面可以用代码一一验证:

 1 //      复制不可变对象
 2         NSString *str = @"Shaw";
 3
 4         NSString *strCopy = [str copy];
 5         NSString *strMCopy = [str mutableCopy];
 6         NSMutableString *mStr = [str copy];
 7
 8 //        [mStr appendString:@"andRoot"];  //运行时crash:‘Attempt to mutate immutable object with appendString:‘
 9
10
11         NSLog(@"%@:%p %@:%p %@:%p",str,str,strCopy,strCopy,strMCopy,strMCopy);
12         strCopy = [str stringByAppendingString:@"andRoot"];           strMCopy = [strMCopy stringByAppendingString:@"andRoot"];
13         NSLog(@"%@:%p %@:%p %@:%p",str,str,strCopy,strCopy,strMCopy,strMCopy);
14
15 //  输出结果
16 2016-04-06 18:06:17.399 test[40355:4843127] Shaw:0x100001050 Shaw:0x100001050 Shaw:0x100600380
17 2016-04-06 18:06:17.400 test[40355:4843127] Shaw:0x100001050 ShawandRoot:0x100103870 Shaw:0x100600380

第6行和第12行代码?

因为strCopy是NSString对象,执行第12行代码,是开辟了另一块空间(0x100103870)的,并没有改变之前那块空间(0x100001050)的对象,所以也是遵守了copy返回的对象(0x100001050)不能被改变这个规则的。

而strMCopy是NSMutableString对象,执行第6行代码,并不会开辟另一块空间,所以这行代码是不能执行成功的。

        // 复制可变对象

        NSMutableString *mStr = [NSMutableString stringWithString:@"Shaw"];
        NSString *strMCopy = [mStr mutableCopy];
        NSString *strCopy = [mStr copy];
//        NSLog(@"%@:%p %@:%p %@:%p",mStr,mStr,strMCopy,strMCopy,strCopy,strCopy);

        NSMutableString *mStrCopy = [mStr copy]; // 打印结果可以看出mStrCopy和strCopy其实是同一个对象,也就是说可变对象的copy只能新开一块空间出来,之后再copy也都是指向这块空间的对象。

        // [mStrCopy appendString:@"andShaw"];  // 运行时crash:unrecognized selector sent to instance 0x7761685345‘

        NSLog(@"%@:%p %@:%p %@:%p %@:%p",mStr,mStr,strMCopy,strMCopy,strCopy,strCopy,mStrCopy,mStrCopy);

        strMCopy = [strMCopy stringByAppendingString:@"andRoot"]; // 会放在新地址
        strCopy = [strCopy stringByAppendingString:@"andRoot"];  //  会放在新地址

        NSLog(@"%@:%p %@:%p %@:%p",mStr,mStr,strMCopy,strMCopy,strCopy,strCopy);

//  输出结果

2016-04-06 19:15:09.413 test[40489:4866634] Shaw:0x100400290 Shaw:0x1004004d0 Shaw:0x7761685345 Shaw:0x7761685345
2016-04-06 19:15:09.414 test[40489:4866634] Shaw:0x100400290 ShawandRoot:0x100400900 ShawandRoot:0x100400550

其实复制不可变对象,没有太大必要去使用mutableCopy,因为反正你都改变不了它的值。


  • retain weak strong(用rayWenderlich的文章来说)

  weak strong是ARC引入的关键词。

  strong指针

  NSString *firstName = @"Ray";

  firstName这个strong指针拥有@"Ray"对象

  

  此时猜想一个textField,当输入Ray

  self.textField.text = @"Ray";

  此时有两个strong指针指向此对象

textField中的文字变化 变成Rayman

此时就变成上图的样子

只有当firstName被赋予新值,或者含有此局部变量的方法结束,或者因为firstName是一个实例变量且它所属的那个对象已经deallocated,这种所有权才结束。

当@"Ray"不再被任何强指针拥有,它就被释放了。

把firstName和self.textField.text这种指针称为strong指针,因为它们使对象存在于内存中。

默认情况下的实例变量,局部变量都是强指针。

weak指针

__weak *NSString weakName = self.textField.text;    //  weak指针是需要显式声明的,用__weak关键字

weakName指向对象但并没有拥有它,如果textField内容发生变动,那么@"Rayman"对象不再被任何强指针指向,它会被释放掉。

weak比assign多了一个作用就是当它指向的对象已经被销毁了,它会自己置成nil。

这是非常方便的,因为这防止弱指针继续指向那片已经被释放了的空间,曾经因为这个问题造成了很多bug,你也许有听过"悬摆指针""野指针",但是有了weak指针,这些问题不会出现了。

weak指针多数被用到有父子关系的两个对象上,父对象用strong指向子对象,子对象用weak指向父对象,这样就避免了内存循环,下面是一个例子。

如果是从storyboard中连了线到代码块的,那都是添加到了父视图的子视图树里的,也就是说是有父对象的强指针指向的

 1 //
 2 //  ViewController.h
 3 //  test2
 4 //
 5 //  Created by Shaw on 16/4/6.
 6 //  Copyright © 2016年 Shaw. All rights reserved.
 7 //
 8
 9 #import <UIKit/UIKit.h>
10
11 @interface ViewController : UIViewController
12
13 @property (weak, nonatomic) IBOutlet UITableView *tableView;
14
15 @property (nonatomic,weak) UIScrollView *scrollView;
16
17 @end
#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    UIScrollView *scrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 353, 400, 200)];
    _scrollView = scrollView;
    [self.view addSubview:self.scrollView];

}

这几句代码可以用下图来描述:

担心scrollView对象有两个强指针指向不好释放?

scrollView变量是个局部变量,出了那个方法,就被释放掉了,之后就只有self一个强指针指向它了。

retain

retain在ARC下是不能显式写的,但是在@property(nonatomic,retain)这样写是没问题的。

retain的属性的setter是先release旧值,再retain新值:

@property (nonatomic,retain) NSString *string;

-(void)setString:(NSString *)str{

//  if(str == _string){

//    return;

// }

  [_string release];

  _string = [str retain];

}

时间: 2024-08-04 16:14:25

NSString NSMutableString copy mutableCopy retain weak strong的相关文章

IOS编程学习(2):copy,nonatomic, retain,weak,strong用法

property属性? property:提供成员变量的访问方法的声明.控制成员变量的访问权限.控制多线程时成员变量的访问环境 .property不但可以在interface,在协议protocol.和类别category中也可以使用. synthesize 合成访问器方法? 实现property所声明的方法的定义.其实说直白就像是:property声明了一些成员变量的访问方法 ,synthesize则定义了由property声明的方法.他们之前的对应关系是  property 声明方法 ---

assign, retain, weak, strong, copy,unsafe_unretain

readonly, readwrite:是控制属性的访问权限,readonly只生成getter方法,其他类是无法修改其值的.readwrite是会同时生成getter和setter方法,其他类可以修改其值. assign, retain, weak, strong, copy,unsafe_unretained:在non-ARC中,assign和retain是一组,assign的对象属性引用计数不变,而retain会被+1.对应的在ARC中,weak和strong是一组,weak的对象属性引用

nonatomic, retain,weak,strong用法详解

strong weak strong与weak是由ARC新引入的对象变量属性 ARC引入了新的对象的新生命周期限定,即零弱引用.如果零弱引用指向的对象被deallocated的话,零弱引用的对象会被自动设置为nil. @property(strong) MyClass *myObject; 相当于@property(retain) MyClass *myObject; @property(weak) MyOtherClass *delegate; 相当于@property(assign) MyO

iOS中copy,retain,strong,assign,weak的区别以及使用

使用assign: 对基础数据类型 (NSInteger)和C数据类型(int, float, double, char,等)使用copy: 对NSString使用retain: 对其他NSObject和其子类 assign就是简单的赋值,不更改引用计数,所以直接使用基础数据 copy是直接拷贝内容,成为一个新的对象. retain释放旧的对象,将旧对象的值赋给新的对象,并使新的对象的引用计数加1 retain是指针拷贝 copy是分配新的内存属于内容拷贝,在拷贝之前都会释放旧的对象 在ARC中

【整理】Object-C中的属性(Property)的Setter:assign,copy,retain,weak,strong之间的区别和联系

iOS编程过程中,经常看到一些属性前面有些修饰符,比如copy,retain等. 这些关键字,是Object-C语言中,对于Property的setter. Mac官网: The Objective-C Programming Language – Declared Properties – Setter Semantics 中的解释是: Setter Semantics These attributes specify the semantics of a set accessor. They

深拷贝和浅拷贝以及NSString的copy retain

浅拷贝就比如像引用类型,而深拷贝就比如值类型. 浅拷贝是指源对象与拷贝对象共用一份实体,仅仅是引用的变量不同(名称不同).对其中任何一个对象的改动都会影响另外一个对象.举个例子,一个人一开始叫张三,后来改名叫李四了,可是还是同一个人,不管是张三缺胳膊少腿还是李四缺胳膊少腿,都是这个人倒霉. 深拷贝是指源对象与拷贝对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响.举个例子,一个人名叫张三,后来用他克隆(假设法律允许)了另外一个人,叫李四,不管是张三缺胳膊少腿还是李四缺胳膊少腿都不会

【iOS面试系列-1】iOS中@property 后assign,copy,retain,weak,strong的意义与区别(必考-必须详细掌握)

来源:网络 assign: 普通(简单)赋值,一般常用于基本数据类型,常见委托设计模式,一次来防止循环引用.不更改索引计数(Reference Counting). 对基础数据类型 (NSInteger,CGFloat)和C数据类型(int, float, double, char, 等等) retain:保留计数,获得到了对象的所有权,引用计数在原有基础上+1.释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1 .我们给那块内存设一个引用计数,当内存被分配并且赋值给a时,引用

iOS中assign,copy,retain之间的区别以及weak和strong的区别

@property (nonatomic, assign) NSString *title; 什么是assign,copy,retain之间的区别? assign: 简单赋值,不更改索引计数(Reference Counting). copy: 建立一个索引计数为1的对象,然后释放旧对象 retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1 weak 和strong的区别: (weak和strong)不同的是 当一个对象不再有strong类型的指针指向它的时候 它会

copy,assign,strong,retain,weak,readonly,nonatomic的区别

copy与retain:1.copy其实是建立了一个相同的对象,而retain不是:2.copy是内容拷贝,retain是指针拷贝:  3.copy是内容的拷贝 ,对于像NSString,的确是这样,但是如果copy的是一个NSArray呢?这时只是copy了指向array中相对应元素的指针.这便是所谓的"浅复制".4.copy的情况:NSString *newPt = [pt copy];此时会在堆上重新开辟一段内存存放@"abc" 比如0X1122 内容为@&q