`
cuichang
  • 浏览: 92654 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

关于self.用法的一些总结

阅读更多

最近有人问我关于什么时候用self.赋值的问题, 我总结了一下, 发出来给大家参考. 有什么问题请大家斧正.

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

[/lang]
@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;
        self.myObject = aMyObject; //myObject retainCount = 2;
        [aMyObject release];//myObject 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. 但这个是官方不提倡的, 

代码比较简单, 我还是发出来, 高人们可以忽略了.[

 

转自: http://www.cocoachina.com/bbs/read.php?tid-12850-page-1.html

分享到:
评论

相关推荐

    Python语言基础项目案例:日期编写.pptx

    class Date(): def __init__(self,y,m,d): self.y = y self.m = m self.d = d def show(self): print("日期为%s年%s月%s日"%(self.y,self.m,self.d)) @classmethod def del_date(cls,date): y,m,d = date....

    ios-iOS基于MBProgressHUD的二次封装,一行搞定,使用超简单.zip

    MBProgressHUD的使用,临时总结了几款最常用的使用场景 源码下载:https://github.com/TangledHusky/YJProgressHUD 使用说明:http://www.cnblogs.com/yajunLi/p/5822702.html 1、提示消息 用法: ...

    location.href用法总结(最主要的)

    self.location.href=”/url” 当前页面打开URL页面 location.href=”/url” 当前页面打开URL页面 windows.location.href=”/url” 当前页面打开URL页面,前面三个用法相同。 this.location.href=”/url” 当前页面...

    ETSI ES 201 873-1 V2.2.1(中文版)

    5.2.1.1 使用传参的方法传递参数.................................................................................................................. 22 5.2.1.2 使用传值的方法传递参数.......................

    PHP中的self关键字详解

    鉴于此,本文先对几个关键字做对比和区分,再总结self的用法。 与parent、static以及this的区别 要想将彻底搞懂self,要与parent、static以及this区分开。以下分别做对比。 parent self与parent的区分比较容易:...

    如何解决python的异常处理方法总结

    python 编辑器推荐使用python tools for visual studio ,个人感觉是最好用的Python 编辑工具,比Wing 之类的好用多了。   VPTS 打开使用Wing 编辑过的py 文件,如果编辑任何代码都提示语法错误, 是因为...

    vue事件修饰符和按键修饰符用法总结

    之前关于vue事件修饰符和按键修饰符的一点分析,最近需要回顾,就顺便发到随笔上了 在事件处理程序中调用 event.preventDefault() 或 event.stopPropagation() 是非常常见的需求。尽管我们可以在 methods 中轻松实现...

    javascript中的self和this用法小结

    本篇文章主要是对javascript中的self和this用法进行了详细的总结介绍,需要的朋友可以过来参考下,希望对大家有所帮助

    对Python中9种生成新对象的方法总结

    下面我们使用9种方法来生成新的对象: point1 = Point(1, 2) point2 = eval({}({}, {}).format(Point, 1, 2)) point3 = globals()[Point](1, 2) point4 = locals()[Point](1, 2) point5 = getattr(sys....

    初学者python笔记(静态属性、类方法、静态方法、类的组合)

    文章目录类的三大方法1、静态属性2、类方法、静态方法3、三大方法总结类的组合1、用法分析2、面试案例分析 本篇文章是上一篇:初学者python笔记(面向对象编程、类与对象)的后续篇,是关于Python中面向对象编程的更...

    【GNN综述_2021_11】Graph Self-Supervised Learning: A Survey

    在图自监督学习的框架下,我们及时全面地回顾了使用SSL技术处理图数据的现有方法。我们构建了一个统一的框架,在数学上形式化了图 SSL 的范式。根据借口任务的目标,我们将这些方法分为四类:基于生成的方法、基于...

    零基础入门python3.7 ——基础知识总结(十七) self详解以及对象动态添加方法

    开发中一看到self就知道应该怎么使用它。 二。认识self 假如说有一个关于汽车的类。那么也就意味着可以通过汽车这个类可以创建出成千上万两相同的汽车。那么随之产生的问题就是这么多一样的汽车怎么保证汽车的主人能...

    Python面向对象实现一个对象调用另一个对象操作示例

    本文实例讲述了Python面向对象实现一个对象调用另一个对象操作。...4.属性的赋值,最好用方法封装起来使用 __str__和__init__方法的举例: # -*- coding:utf-8 -*- #! python3 class Cat: def __init_

    python多线程用法实例详解

    今天在学习尝试学习python多线程的时候,突然发现自己一直对super的用法不是很清楚,所以先总结一些遇到的问题。当我尝试编写下面的代码的时候: 复制代码 代码如下:class A():  def __init__( self ):  print “A...

    Self-Supervised Visual Feature Learning With Deep Neural Network

    为了避免收集和标注大量的数据所需的巨大开销,作为无监督学习方法的一个子方法——自监督学习方法,可以在不使用任何人类标注的标签的情况下,从大规模无标记数据中学习图像和视频的一般性特征。本文对基于深度学习...

    php self,$this,const,static,-gt;的使用

    、在类的内部方法访问已经声明为const及static的属性时,使用self::$name的形式。注意的是const属性的申明格式,const PI=3.14,而不是const $PI=3.14 复制代码 代码如下: class clss_a { private static $name=”...

    NSpredicate

    最近常用到NSpredicate ,自己汇总了一些用法,总结NSpredicate 用法,

    类与对象~~~~~~

    类class与对象object: 万事万物,皆为对象。 类和实例都是对象。... def eat(self): # 实例方法创建,def+方法名(self): print('吃饭,选择用筷子。') # 方法的具体执行过程,即定义“能做什么”

Global site tag (gtag.js) - Google Analytics