`
ydbc
  • 浏览: 718420 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

ios strong和weak

 
阅读更多
iOS5中加入了新知识,就是ARC,其实我并不是很喜欢它,因为习惯了自己管理内存。但是学习还是很有必要的。

在iOS开发过程中,属性的定义往往与retain, assign, copy有关,我想大家都很熟悉了,在此我也不介绍,网上有很多相关文章。
现在我们看看iOS5中新的关键字strong, weak, unsafe_unretained. 可以与以前的关键字对应学习strong与retain类似,weak与unsafe_unretained功能差不多(有点区别,等下会介绍,这两个新关键字与assign类似)。在iOS5中用这些新的关键字,就可以不用手动管理内存了,从java等其它语言转过来的程序员非常受用。

strong关键字与retain关似,用了它,引用计数自动+1,用实例更能说明一切

1. @property(nonatomic,strong)NSString*string1;
2. @property(nonatomic,strong)NSString*string2;

有这样两个属性,

1. @synthesizestring1;
2. @synthesizestring2;


猜一下下面代码将输出什么结果?

1. self.string1=@"String1";
2. self.string2=self.string1;
3. self.string1=nil;
4. NSLog(@"String2=%@",self.string2);


结果是:String 2 = String 1

由于string2是strong定义的属性,所以引用计数+1,使得它们所指向的值都是@"String 1", 如果你对retain熟悉的话,这理解并不难。

接着我们来看weak关键字:
如果这样声明两个属性:

1. @property(nonatomic,strong)NSString*string1;
2. @property(nonatomic,weak)NSString*string2;

并定义


1. @synthesizestring1;
2. @synthesizestring2;

再来猜一下,下面输出是什么?


1. self.string1=[[NSStringalloc]initWithUTF8String:"string1"];
2. self.string2=self.string1;
3. self.string1=nil;
4. NSLog(@"String2=%@",self.string2);

结果是:String 2 = null

分析一下,由于self.string1与self.string2指向同一地址,且string2没有retain内存地址,而 self.string1=nil释放了内存,所以string1为nil。声明为weak的指针,指针指向的地址一旦被释放,这些指针都将被赋值为 nil。这样的好处能有效的防止野指针。在c/c++开发过程中,为何大牛都说指针的空间释放了后,都要将指针赋为NULL. 在这儿用weak关键字帮我们做了这一步。

接着我们来看unsafe_unretained
从名字可以看出,unretained且unsafe,由于是unretained所以与weak有点类似,但是它是unsafe的,什么是unsafe的呢,下面看实例。
如果这样声明两个属性:
并定义
1. @property(nonatomic,strong)NSString*string1;
2. @property(nonatomic,unsafe_unretained)NSString*string2;

再来猜一下,下面的代码会有什么结果?


1. self.string1=[[NSStringalloc]initWithUTF8String:"string1"];
2. self.string2=self.string1;
3. self.string1=nil;
4. NSLog(@"String2=%@",self.string2);

请注意,在此我并没有叫你猜会有什么输出,因为根本不会有输出,你的程序会crash掉。

原因是什么,其实就是野指针造成的,所以野指针是可怕的。为何会造成野指针呢?同于用unsafe_unretained声明的指针,由于 self.string1=nil已将内存释放掉了,但是string2并不知道已被释放了,所以是野指针。然后访问野指针的内存就造成crash. 所以尽量少用unsafe_unretained关键字。

strong,weak,unsafe_unretained往往都是用来声明属性的,如果想声明临时变量就得用__strong, __weak, __unsafe_unretained, __autoreleasing, 其用法与上面介绍的类似。
还是看看实例吧。

1. __strongNSString*yourString=[[NSStringalloc]initWithUTF8String:"yourstring"];
2. __weakNSString*myString=yourString;
3. yourString=nil;
4. __unsafe_unretainedNSString*theirString=myString;
5. //现在所有的指针都为nil

再看一个:

1. __strongNSString*yourString=[[NSStringalloc]initWithUTF8String:"string1"];
2. __weakNSString*myString=yourString;
3. __unsafe_unretainedNSString*theirString=myString;
4. yourString=nil;
5. //现在yourString与myString的指针都为nil,而theirString不为nil,但是是野指针。

在这儿也说一下字符串相关的,如果NSString *str = @"str test";这样将声明一个字符串常量,这样声明的不受上面所说的限制。
如:

1. __strongNSString*yourString=@"teststring";
2. __weakNSString*myString=yourString;
3. yourString=nil;
4. //现在myString还是有值的


NSString *str =[[NSString alloc] initWithString:@"test"];这样返回的也是字符串常量, 效果与 NSString *str = @"test";是一样的。 但得遵循苹果内存管理,在非ARC的情况下还是要调用release,其实不需要调用也不会内存泄漏。

__autoreleasing的用法介绍:

在c/c++,objective-c内存管理中有一条是:谁分配谁释放。__autoreleasing则可以使对像延迟释放。比如你想传一个未初始化地对像引用到一个方法当中,在此方法中实始化此对像,那么这种情况将是__autoreleasing表演的时候。看个示例:

1. -(void)generateErrorInVariable:(__autoreleasingNSError**)paramError{
2. NSArray*objects=[[NSArrayalloc]initWithObjects:@"Asimpleerror",nil];
3. NSArray*keys=[[NSArrayalloc]initWithObjects:NSLocalizedDescriptionKey,nil];
4. NSDictionary*errorDictionary=[[NSDictionaryalloc]initWithObjects:objectsforKeys:keys];
5. *paramError=[[NSErroralloc]initWithDomain:@"MyApp"code:1userInfo:errorDictionary];
6. }
7. -(void)test
8. {
9. NSError*error=nil;
10. [selfgenerateErrorInVariable:&error];
11. NSLog(@"Error=%@",error);
12. }
被编译器翻译后就变为:
1. -(void)test
2. {
3. NSError*error=nil;
4. NSError*__autoreleasingtmp=error;
5. [selfgenerateErrorInVariable:&tmp];
6. error=tmp;
7. NSLog(@"Error=%@",error);
8. }
这样即便在函数内部申请的空间,在函数外部也可以使用,同样也适合谁分配谁释放的原则。
同样下面的代码也是类似原因, 只不过在没有开启ARC的情况下适用:


1. -(NSString*)stringTest
2. {
3. NSString*retStr=[NSStringstringWithString:@"test"];
4.
5. return[[retStrretain]autorelease];
6. }

开启ARC后,应改为:经过测试下面这种方法是可行的,不过都不建意这样写代码, __autoreleasing官网的例子是用在传引用参数当中(像上面那个NSError)。所以最好不要像下面这样用

1. -(NSString*)stringTest
2. {
3. __autoreleasingNSString*retStr=[NSStringalloc]initWithString:@"test"];
4.
5. returnretStr;
6. }

1. -(NSString*)stringTest__attribute__((ns_returns_autoreleased)){NSString*retStr=[NSStringalloc]initWithString:@"test"];returnretStr;}
与上面功能相似。返回一个autorelease。

关于methord family, 如果方法名是以alloc, init, copy, mutablecopy,new字符开头的,那么它们的返回值会被retain的,其它的默认就是autorelease返回的。下面介绍一下返回值的例子:


1. -(id)foo__attribute((ns_returns_retained));//返回值retain+1,init,new,alloc,copy,mutablecopydefaultarethis
2. -(id)foo__attribute((ns_returns_not_retained));//返回指针弱引用,
3. -(id)foo__attribute((ns_returns_autoreleased));//返回autorlease,exceptdefault,arethis

init开头的方法有一个规定,一定要返回id或父类,子类的指针,不然要有warning.
这儿是原话:
initmethods must be instance methods and must return an Objective-C pointer type. Additionally, a program is ill-formed if it declares or contains a call to aninitmethod whose return type is neitheridnor a pointer to a super-class or sub-class of the declaring class (if the method was declared on a class) or the static receiver type of the call (if it was declared on a protocol).
当然你也可以打破这个规定,如果你这样声明方法:

1. -(void)initStr__attribute__((objc_method_family(none)));
那么就是正确的。


分享到:
评论

相关推荐

    iOS 中weak的实现代码示例

    只要学过 iOS 的人,都会对 strong、weak、copy等关键字应该都会很熟悉。weak 属性关键字就是弱引用,它不会增加引用计数但却能保证指针的安全访问,在对象释放后置为 nil,从而避免错误的内存访问。主要为了解决...

    IOS中(assign,retain,copy,weak,strong)的区别以及nonatomic的含义

    IOS中(assign,retain,copy,weak,strong)的区别以及nonatomic的含义 我们在声明@property 属性时,总是要在括号中写上assign、retain、copy、weak、strong中的一个,很多时候,我们仅仅只是按照习惯去写经常写...

    iOS Programming: The Big Nerd Ranch Guide (4th Edition) 2014 epub

    ARC and strong and weak references Handling touch events and gestures Toolbars, navigation controllers, and split view controllers Using Auto Layout to scale user interfaces Using Dynamic Type to ...

    iOS Programming: The Big Nerd Ranch Guide (4th Edition) (Big Nerd Ranch Guides)

    ARC and strong and weak references Handling touch events and gestures Toolbars, navigation controllers, and split view controllers Using Auto Layout to scale user interfaces Using Dynamic Type to...

    iOS开发实习面试题目

    weak,assign,strong的意义和区别? atomic,nonatomic的意义和区别? OC中有没有多继承?OC中怎么实现多继承功能? category和subclass的异同?平时怎样选择? OC中的变量是怎样存储的? block是怎样改变外界的变量的?...

    iOS面试题分享

    简述OC中内存管理机制。与retain配对使用的方法是dealloc还是release,为什么?需要与alloc配对使用的方法是dealloc还是...readwrite,readonly,assign,retain,copy,nonatomic 、atomic、strong、weak属性的作用

    iOS开发系列-ARC浅解

    在使用ARC开发过程中,开发者只需考虑strong / weak 的使用,不再需要考虑对象何时要retain,release/autorealease。使用ARC一般不会降低程序的效率。  二、ARC的工作原理  ARC一个很重要的原则是:只要某个对象...

    iOS 对象属性详细介绍

    retain,strong, copy,weak,assign,readonly, readwrite, unsafe_unretained 下面来分别讲讲各自的作用和区别: retain,计数器加1, (增加一个指向内存的指针) 对应release(计数器-1) setter 方法对参数进行 ...

    ios 5 ARC 完全指南

    介绍arc的不错的书籍,weak ,strong,unsafe_unretain ,block的介绍

    IOS property属性详细介绍使用注意事项

    IOS property属性 原子性 atomic nonatomic 访问权限 readWrite readOnly 内存管理 strong retain copy assign weak unsafe_unretained 方法命名 getter = setter = <name> 结论 1、原子性  (1...

    iOS内存管理

    强引用、弱引用 weak和strong只有你打开ARC时才会被要求使用

    iOS 5.0 ARC开发详细解读

    最全面的ARC解读,手把手教会你。文档从基础到高级,从IBOutlet、Property、delloc开始讲解,重点讲解了weak、strong等的用法

    iOS蓝牙开发数据实时传输

    随着iOS项目开发 很多app需要通过蓝牙与设备连接 蓝牙开发注意: 先定义中心设备和外围设备以及遵守蓝牙协议 @interface ViewController() @property (strong, nonatomic) CBCentralManager *manager; @property ...

    iOS常见的几个修饰词深入讲解

    主要给大家介绍了关于iOS常见的几个修饰词的相关资料,iOS修饰词包括assign、weak、strong、retain、copy、nonatomic、atomic、readonly、readwrite,文中通过示例代码介绍的非常详细,需要的朋友可以参考下

    iOS/OSX内存管理(二):借助工具解决内存问题

    上一篇博客《iOS/OSX内存管理(一):基本概念与原理》主要讲了iOS/OSX内存管理中引用计数和内存管理规则,以及引入ARC新的内存管理机制之后如何选择ownershipqualifiers(__strong、__weak、__unsafe_unretained和__...

    IOS 避免self循环引用的方法的实例详解

    IOS 避免self循环引用的方法的实例详解 示例代码: // - weak & strong #define myWeakify(VAR) \ try {} @finally {} \ __weak __typeof__(VAR) VAR##_myWeak_ = (VAR) #define myStrongify(VAR) \ try {} @...

    IOS 开发之查看大图的实现代码

    IOS 开发之查看大图的实现代码 本项目是取自传智播客的教学项目,加入笔者的修改和润饰。 1. 项目名称:查看大图 2. 项目截图展示 3. 项目功能 左右滑动查看图片 支持缩放功能 点击中间按钮移动图片 4. 项目代码 ...

    Swift4.0源代码最新201802

    20.自动引用计数(strong,weak,unowned).playground 21.检测API.playground 22.?对象的标识.playground 23.注释.playground 24.?元类型.playground 25.控件命名.playground 26.对象判等.playground 27.探究Self的用途...

    iOS在页面销毁时如何优雅的cancel网络请求详解

    前言 大家都知道,当一个网络请求发出去之后,如果不管不顾,有可能出现以下情况: 进入某个页面,做了某种操作(退出页面、切换某个...@property (strong/weak, nonatomic) XXRequest *xxrequest1; 属性具体用stro

Global site tag (gtag.js) - Google Analytics