转自sina博客   可以先看下千锋视频可以先了解下“遛狗原理”。这篇写的蛮好,转了过来……

   关于什么时间用self. , 其实是和Obj-c的存取方法有关, 不过网上很多人也都这么解答的, 那它为什么和存取方法有关? 怎么有关的? 并没有多少人回答出来. 同时关于内存管理的内容, 请大家看旺财勇士的Objective-C内存管理总结~CC专版 , 有些东西我就不多解释了.   进入正题, 我们经常会在官方文档里看到这样的代码:

   MyClass.h

  @interface MyClass : NSObject {
       MyObject *myObject;
   }
  

  @property (nonatomic, retain) MyObject *myObject;
  

  @end

  

  MyClass.m

  @synthesize myObject;
 
  -(id)init{
        if(self = [super init]){
           MyObject * aMyObject = [[MyObject alloc] init];
           self.myObject = aMyObject;
           [aMyObject release];
       }
      return self;
  }
  有人就问, 为什么要这么复杂的赋值? 为什么要加self. ? 直接写成self.myObject = [[MyObject alloc] init];不是也没有错么? 不加self有时好像也是正常的?现在我们来看看内存管理的内容:

  先看间接赋值的:

    1.加

       self.MyObject *aMyObject = [[MyObject alloc] init]; //aMyObject retainCount = 1; 内存计数器retainCount
       self.myObject = aMyObject; //myObject retainCount = 2;内存计数器retainCount+1
       [aMyObject release];//myObject retainCount = 1;内存计数器release : retainCount-1

    

    2. 不加 

      self.MyObject * aMyObject = [[MyObject alloc] init]; //aMyObject retainCount = 1;
      myObject = aMyObject; //myObject retainCount = 1;
      [aMyObject release];//对象己经被释放

    再看直接赋值的:

    3.加self.

      self.myObject = [[MyObject alloc] init]; //myObject retainCount = 2; 容易造成内存泄露

    4.不加self.

      myObject = [[MyObject alloc] init]; //myObject retainCount = 1;  对象内存已释放,如果调用,会有异常

    现在是不是有点晕, 我们先来把代码改一下, 官方的一种常见写法:

      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]; 为什么会有内存泄露?
  关于nonatomic我不多解释了, 它不是我要讲的重点, 而且我也没完全搞清楚, 不误导大家. 我只说assign, retain ,copy.

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调用.现在回头说说我们开始的那四个赋值,

  当不用self.的时候,  那句话只是一般的赋值, 把一个指针赋给另一个指针, 不会对分配的内存有任何影响, 所以2中不要最后[aMyObject release];这句话和4是一回事. 这里就不多说了.我们看看1和3,

  当调用setMyObject:方法时, 对newValue 做了一次retain操作, 我们必须把原来的newValue释放掉, 不然就会内存泄露, 在1里, 我们有个aMyObject可以用来释放, 在3里, 我们无法释放它, 所以, 在3里, 我们会多出来一个retainCount. 内存泄露了.

  说了这么多, 我只想让大家清楚, 什么是调用属性本身, 什么是调用存取方法. 怎么样才能避免内存泄露, 而且, 以上例子里是在自己类里的调用, 如果这个类被别的类调用时, 更要注意一些,顺便说一下, 如果你想在其它类访问对象属性, 而不是通过存取方法, 你可以用myClass -> myObject来访问, 这样是直接访问对象本身, 不过你先要把myObject设成@public. 但这个是官方不提倡的。

转载于:https://www.cnblogs.com/jackljf/archive/2012/09/17/3589282.html

Objective-C 日记② 关于self用法相关推荐

  1. python日记(四)字典的常见用法

    #author:ne_zha #dictionaryfeng_shen_bang ={1:'哪吒',2:'雷震子',3:'杨戬'}print(feng_shen_bang[1])print(feng_ ...

  2. python 学习日记 —— dict 字典的用法

    什么是字典 什么是字典? 字典是 python 中的一个键(key)值(value)映射的数据结构: 字典是无序的: 字典是可变对象: 字典的 key 必须是唯一的: 字典的定义: 字典通过花括号中用 ...

  3. 《算法笔记》学习日记——6.1 vector的常见用法详解

    目录 6.1 vector的常见用法详解 问题 A: Course List for Student (25) 问题 B: Student List for Course (25) 小结 6.1 ve ...

  4. python中find函数的使用方法_Python学习日记5|BeautifulSoup中find和find_all的用法

    今天是4.20号. 前天晚上看到蒋方舟的一句话: 不要左顾右盼.慢慢积累,慢慢写吧.毕竟除了这样单调的努力,我什么也做不了. 而现在的自己就是个十足的壁花少年. 在进入正题前先说一下每次完成代码后,可 ...

  5. 69:shell脚本介绍 | shell脚本结构 | 执行data命令用法 | shell脚本中变量

    2019独角兽企业重金招聘Python工程师标准>>> 1.shell脚本介绍: shell是一种脚本语言和传统的开发语言相比,会比较简单: shell有自己语法,可以支持逻辑判断. ...

  6. anaconda tensorflow 2.3_TensorFlow 速成 | 统计师的Python日记 第13天

    本文是[统计师的Python日记]第13天的日记 回顾一下: 第1天学习了Python的基本页面.操作,以及几种主要的容器类型. 第2天学习了python的函数.循环和条件.类. 第3天了解了Nump ...

  7. LightGBM用法速查表

    LightGBM用法速查表 1.读取csv数据并指定参数建模 # coding: utf-8 import json import lightgbm as lgb import pandas as p ...

  8. Linux GCC用法

    GCC原名为GNU C语言编译器(GNU C Compiler),只能处理C语言.但其很快扩展,变得可处理C++,后来又扩展为能够支持更多编程语言,如Fortran.Pascal.Objective ...

  9. a as as big rat_你知道填空中as的这个变态用法吗?

    在填空学习中,我们一定要掌握关键逻辑提示词或者提示标点符号的用法.根据这些逻辑提示标志所展现的逻辑方向,我们才能将对应信息做适当的同反向加工处理,进而推导出答案. 在众多的逻辑提示标志中,as这个词特 ...

  10. day28:检测磁盘io|自定义时段查看tomcat 日记|打印城市名字|代码上线|统计网站并发量...

    2019独角兽企业重金招聘Python工程师标准>>> 1.有一台阿里云的机器,接到反映说服务器的磁盘 io 很高,登录服务器查看,并没有发现问题,怀疑是间歇性的,看到造成磁盘 io ...

最新文章

  1. Python中多个数组行合并及列合并的方法总结
  2. latex换页_备忘 | Latex 双栏模式下表格太长怎么办?
  3. ssh html项目,SSH项目-学生管理系统
  4. Message popover
  5. linux中 ls |wc -l
  6. JAVA包装类及自动封包解包示例代码
  7. vivox6android版本5.1,vivo X6 Plus的手机系统是什么?能升级安卓5.0吗?
  8. 关于Runtime.getRuntime().exec()运行python代码失败的问题
  9. 【Python实例第18讲】affinity propagation聚类算法
  10. Vue 过滤器filters
  11. 【ZZ】神与学霸的区别
  12. paip.web数据绑定 下拉框的api设计 选择框 uapi python .net java swing jsf总结
  13. Unity AssetBundle加载的理解
  14. 产品经理必修30本书
  15. 在windows 2003系统上安装诺基亚pc套件以及笔记本通过PC套件上网
  16. 东南计算机专硕学硕区别,学硕VS专硕,你该如何选择?
  17. python量化策略—— alpha 三因子策略(1)
  18. 非线性优化汇总——Matlab优化工具箱(持续更新中)
  19. 刷题记录(NC235611 牛牛国的战争,NC23803 DongDong认亲戚,NC235622 叠积木)
  20. 如何制作个人商业网站

热门文章

  1. package.json详解
  2. 个人理解的块状格式化上下文
  3. React Native 0.21 发布 (翻译Changelog)
  4. 关于Oracle分区的一篇文章
  5. SoftGrid教程——排序服务器
  6. 【翻译】FisheyeMultiNet: Real-time Multi-task Learning Architecture for Surround-view Automated Parking
  7. Spark的StandAlone模式原理和安装、Spark-on-YARN的理解
  8. Hibernate常用查询
  9. Asp.Net母版页元素ID不一致的体现
  10. You Probably Dont Need Derived State