ios何时使用self
来源:互联网 发布:江苏破获网络诈骗团伙 编辑:程序博客网 时间:2024/06/05 15:37
原文链接:http://blog.csdn.net/lvxiangan/article/details/27204265
从内存管理来说明使用self.和不使用self的区别:
ViewController.h文件,使用Student类,代码如下:
- #import <UIKit/UIKit.h>
- @class Student;
- @interface ViewController : UIViewController{
- Student *_student;
- }
- @property (nonatomic, retain) Student *student;
- @end
- #import "ViewController.h"
- #import "Student.h"
- @implementation ViewController
- @synthesize student = _student;
- - (void)didReceiveMemoryWarning
- {
- [super didReceiveMemoryWarning];
- }
- #pragma mark - View lifecycle
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- }
- - (void) dealloc
- {
- [_student release];
- _student = nil;
- [super dealloc];
- }
在ViewController.m的viewDidLoad方法中创建一个Student类的对象
- Student *mystudent = [[Student alloc] init];
- self.student = mystudent;
- [mystudent release];
接下来就需要从内存角度来分析它们之间的区别了:
- 1、加self的方式:
- Student *mystudent = [[Student alloc] init]; //mystudent 对象 retainCount = 1;
- self.student = mystudent; //student 对象 retainCount = 2;
- [mystudent release]; //student 对象 retainCount = 1;
- //student的property 是retain 默认使用self.student引用计数+1。
- 2、不加self的方式
- Student *mystudent = [[Student alloc] init]; //mystudent 对象 retainCount = 1;
- student = mystudent; //student 对象 retainCount = 1;
- [mystudent release]; //student 对象内存已释放,如果调用,会有异常
- 3、加self直接赋值方式
- self.student = [[Student alloc] init]; //student 对象 retainCount = 2;容易造成内存泄露
转载:http://jordy.easymorse.com/?p=805
个人总结:只需要在属性初始化的时候使用self.属性,其他时候直接使用属性名就行;使用self.是 使retaincount+1,为了确保当前类对此属性具有拥有权
个人使用习惯:
- @interface CustomClass : UIViewController
- {
- NSString *str
- }
- @property (retain, nonatomic) NSString *str;
- @implementation CustomClass
- @synthesize str;
- -(void)viewDidLoad
- {
- //方法一 用alloc必须手动释放一次
- self.str = [[NSString alloc]initWithString:@"my str"];
- [str release];
- //方法二 用类方法不用
- self.str = [NSString stringWithString:@"my str"];
- 以后调用时直接使用str,不必使用self.str
- [str appendString:@"\n"];
- }
- //在dealloc中必须释放
- - (void)dealloc
- {
- //方法一
- [str release];
- str = nil;
- //方法二
- self.str = nil;
- [super dealloc];
- }
看图:
.h文件,view2有retain参数
.m文件,
不使用self.的方法赋值
使用self.的方法赋值
使用self.的方法赋值的retaincount是对的。
@property 关键字的作用是 给实例变量在.h文件里创建一个set/get函数的申明。等同在.h文件里面给实例变量写set/get函数申明。
@property (nonatomic,retain) UIView *view2;
等于
-(UIView*)getView2;
-(void)setView2:(UIView*)view;
在.m文件里的@synthesize关键字就是自动实现set/get函数。
get方法是:
- -(MyObject*)myObject{
- return _myObject;
- }
Set方法是:
- // assign
- -(void)setMyObject:(id)newValue{
- _myObject = newValue;
- }
- // retain
- -(void)setMyObject:(id)newValue{
- if (_myObject != newValue) { // 若先前已经赋予相同的值,则不会引起计数器变化
- [_myObject release];
- _myObject = [newValue retain]; // newValue的计数器值为1,再次retain后变为2,所以self.计数器会加1
- }
- }
- // copy
- -(void)setMyObject:(id)newValue{
- if (_myObject != newValue) { // 同上
- [_myObject release];
- _myObject = [newValue copy]; // 同上
- }
- }
retain关键字的作用是,在实现set函数内部,retain当前变量,具体实现是这样:
- -(void)setView2:(UIView*)view{
- [_view2 release];
- _view2 = [view retain];
- }
而self.view2 = tView;等于[self setView2:tview];也就是说,如果不用self.调用实例变量,retain关键字是不起作用的。
执行代码self.view2 = tView之后,tView和view2都是同一个对象,只是这个赋值的发操作把tView的retaincount+1了而已。所以当 [tView release]之后,self.view2的retaincount-1。
然后当再次给 self.view2赋值的时候,在set内部会再次release。这样是不会有内存泄露的。
在不使用self.的图片里,为什么在 [tView release]之后,retaincount还是1呢?这是因为 [tView release]之后, tView retaincount实际变成了0,然后tView 就被释放掉了。你后面调用tView.retainCount其实是没意义的,tView已经被释放了。所以你看到的1其实是,retainCount,retainCount2这2个变量前面被赋值的值。你如果改成赋值给一个新的变量,你就会发现是0了。而这个0其实是新的变量的初始化的值0,并不是tView.retainCount返回的0。
这里release会挂掉,但是我把[tView release]写到最后面却不会挂掉。
这里该怎么管理?
不是alloc后,赋给了_view2就该立刻release的嘛?
还有,原来那个问题真的和你说得一样,在不使用self.的时候那个reatinCount真的是上面的值,release后还是上面那个值。
你追问的图片里的红字理解是正确的。使用self.的作用就是在于 调用set函数去给实例变量赋值。不使用self. 直接使用_view2赋值就是等于直接给实例变量赋值,不会经过set函数。在有retain关键字的情况下,set函数里面实现了传入新参数的retain,旧参数的release。所以这样可以更好的管理传参时的内存管理。这就是为什么Apple推荐大家都用self.进行实例变量的赋值。不到万不得已的情况,不要随便直接使用_view2实例变量直接赋值。在遵循使用self.规则前提下,self.view2 = tView;语句之后 就可以立刻对[tView release]. 但是你的代码是直接使用_view2赋值的,没进过set函数,没了tView 没有retain,后面你再[tView release],其实这里tView 就已经释放了。然后你再去访问tView 的retainCount属性,必然是要crash的。
- - (void)setView2:(UIView *)view2{
- [view2 retain];
- //view2.retainCount == 2
- [_view2 release];
- //_view2.retainCount == 0
- _view2 = view2;
- //_view2.retainCount == 2
- }
view2作为属性会自动生成setter和getter方法。self.view2 = tview;会调用上方的setter方法。
那么不使用self.赋值的时候是不是不会调用上面的setter方法来retain呢?
是的你可以试下 _view2 = tview;
self.会默认调用get方法,比如一个变量定义成了retain,则self.之后引用计数就会加1.strong,weak是arc的时候用到的。
官方的一种常见写法:
- MyClass.h
- @interface
MyClass : NSObject { -
MyObject * _myObject; - }
- @property
(nonatomic, retain) MyObject *myObject; - @end
- MyClass.m
- @synthesize
myObject = _myObject;
OK, 你现在再试下, 如果你用self._myObject = aMyObject; 或者 myObject = aMyObject; 你会得到一个错误, 为什么呢, 这里就是和Obj-c的存取方法有关了. 说白了很简单 , 大家都知道, @property (nonatomic, retain) MyObject *myObject; 是为一个属性设置存取方法, 只是平时我们用的方法名和属性名是一样的,现在你把它写成不同的名字, 就会很清楚了. _myObject是属性本身, myObject是存取方法名.
现在我们知道self.是访问属性的存取方法了, 那存取方法又怎么工作的? self.myObject = [[MyObject alloc] init]; 为什么会有内存泄露?
get方法是:
- -(MyObject*)myObject{
-
return _myObject; - }
Set方法是:
- //
assign - -(void)setMyObject:(id)newValue{
-
_myObject = newValue; - }
- //
retain - -(void)setMyObject:(id)newValue{
-
if (_myObject != newValue) { -
[_myObject release]; -
_myObject = [newValue retain]; -
} - }
- //
copy - -(void)setMyObject:(id)newValue{
-
if (_myObject != newValue) { -
[_myObject release]; -
_myObject = [newValue copy]; -
} - }
其实这些方法里还有别的内容, 并不只是这些. 而且这些方法可以被重写. 比如你写一个
- -(MyObject*)myObject{
-
return _myObject; - }
放在你的类里, 你调用self.myObject时(不要把它放在等号左边, 那会调用get方法)就会调用这个方法.
这里多说一句, @property 是为你设置存取方法, 和你的属性无关, 你可以只写一句
- @property
(readonly) NSString *name;
在你的类里实现
- -(NSString*)name{
-
NSLog(@"name"); -
return @ "MyClass"; - }
同样可以用self.name调用.
顺便说一下, 如果你想在其它类访问对象属性, 而不是通过存取方法, 你可以用myClass -> myObject来访问, 这样是直接访问对象本身, 不过你先要把myObject设成@public. 但这个是官方不提倡的,
- ios何时使用self.
- ios何时使用self.
- ios何时使用self.
- ios何时使用self.
- ios何时使用self.
- iOS何时使用self
- ios何时使用self
- iOS 优化内存(四)何时用self
- iOS:strong 与weak何时使用
- iOS block何时可以不使用weakSelf
- 何时使用@()
- 在Objective-C中何时用self.何时不用?
- 在Objective-C中何时用self.何时不用?
- 在Objective-C中何时用self.何时不用?
- 何时使用 Parallel.ForEach,何时使用 PLINQ
- 1 何时使用Class?何时使用Struct?
- 何时使用copy,何时使用strong
- mysql何时使用myisam, 何时使用innodb ?
- [NOTES]C++标准IO
- STM32电源管理
- C# 生成自定义长度的0-z随机字符串
- android(Google公司开发的操作系统)
- 文件处理函数
- ios何时使用self
- UESTC 853 一个简单的走迷宫问题
- TreeList获取节点中的值
- 用ATL开发ActiveX网页控件
- linux下一次性fork多个子进程方法
- AutoScrollViewPager与PageIndicator无限循环混合使用
- HDU2054_A == B ?【模拟题】【大数】【水题】
- VC ++ & sqlite
- C# 轻松获取路径中文件名、目录、扩展名等