iOS何时使用self

本文通过实例详细解析Objective-C中self.的使用方法及其与内存管理的关系,阐述self.与属性之间的联系,帮助读者理解self.的重要性。

何时使用self.在网上搜索或者论坛里的回复大多都是简简单单的说这与objc的存取方法有关,如何与存取方式有关究竟他们之间的是什么样的关系就很少有同学回答了。下面以代码来说明问题:

创建一个Student类,继承NSObject类,代码:

<span class="lnum" style="margin: 0px; padding: 0px;">   1:  </span>#import <Foundation/Foundation.h>
   2:   
<span class="lnum" style="margin: 0px; padding: 0px;">   3:  </span>@<span class="kwrd" style="margin: 0px; padding: 0px;">interface</span> Student : NSObject{
   4:   
<span class="lnum" style="margin: 0px; padding: 0px;">   5:  </span>    NSString *idd;
   6:      NSString *name;
<span class="lnum" style="margin: 0px; padding: 0px;">   7:  </span>}
   8:  @property (nonatomic, retain) NSString *idd;
<span class="lnum" style="margin: 0px; padding: 0px;">   9:  </span>@property (nonatomic, retain) NSString *name;
  10:   
<span class="lnum" style="margin: 0px; padding: 0px;">  11:  </span>@end

.m文件 代码:

<span class="lnum" style="margin: 0px; padding: 0px;">   1:  </span>#import <span class="str" style="margin: 0px; padding: 0px;">"Student.h"</span>
   2:   
<span class="lnum" style="margin: 0px; padding: 0px;">   3:  </span>@implementation Student
   4:  @synthesize idd,name;
<span class="lnum" style="margin: 0px; padding: 0px;">   5:  </span> 
   6:  - (void)dealloc
<span class="lnum" style="margin: 0px; padding: 0px;">   7:  </span>{
   8:      [idd release];
<span class="lnum" style="margin: 0px; padding: 0px;">   9:  </span>    [name release];
  10:      [super dealloc];
<span class="lnum" style="margin: 0px; padding: 0px;">  11:  </span>}
  12:   
<span class="lnum" style="margin: 0px; padding: 0px;">  13:  </span> 
  14:  @end

使用@propety @synthesize实现Student的成员属性的set get方法。通常我们在其他类里访问Student的成员属性的做法:

获取student的名字通过student.name,给名字赋值[student setName:@“jordy”]; 其中studentStudent类对象,如果在Student类内部访问其成员属性使用[self setName:@”jordy”], 访问使用self.name;

注意:上述的代码,由于wordpress的原因,代码中的字符会自动保存为中文格式。你在使用时记得改为英文格式。

Student.hStudent.m文件,是我们习惯性的写法,但似乎还是不能解释什么加self和不加self的区别,请看下面代码,是另一种习惯性的写法,还以Student类为例:

.h文件 代码:

<span class="lnum" style="margin: 0px; padding: 0px;">   1:  </span>#import <Foundation/Foundation.h>
   2:   
<span class="lnum" style="margin: 0px; padding: 0px;">   3:  </span>@<span class="kwrd" style="margin: 0px; padding: 0px;">interface</span> Student : NSObject{
   4:   
<span class="lnum" style="margin: 0px; padding: 0px;">   5:  </span>    NSString *_idd;
   6:      NSString *_name;
<span class="lnum" style="margin: 0px; padding: 0px;">   7:  </span>}
   8:  @property (nonatomic, retain) NSString *idd;
<span class="lnum" style="margin: 0px; padding: 0px;">   9:  </span>@property (nonatomic, retain) NSString *name;
  10:   
<span class="lnum" style="margin: 0px; padding: 0px;">  11:  </span>@end

 

.m文件 代码:

<span class="lnum" style="margin: 0px; padding: 0px;">   1:  </span>#import <span class="str" style="margin: 0px; padding: 0px;">"Student.h"</span>
   2:   
<span class="lnum" style="margin: 0px; padding: 0px;">   3:  </span>@implementation Student
   4:  @synthesize idd = _idd;
<span class="lnum" style="margin: 0px; padding: 0px;">   5:  </span>@synthesize name = _name;
   6:   
<span class="lnum" style="margin: 0px; padding: 0px;">   7:  </span>- (<span class="kwrd" style="margin: 0px; padding: 0px;">void</span>)dealloc
   8:  {
<span class="lnum" style="margin: 0px; padding: 0px;">   9:  </span>    [_idd release];
  10:      _idd = nil;
<span class="lnum" style="margin: 0px; padding: 0px;">  11:  </span>    [_name release];
  12:      _name = nil;
<span class="lnum" style="margin: 0px; padding: 0px;">  13:  </span>    [super dealloc];
  14:  }
<span class="lnum" style="margin: 0px; padding: 0px;">  15:  </span> 
  16:   
<span class="lnum" style="margin: 0px; padding: 0px;">  17:  </span>@end
 

可以注意到上述代码,与之前的代码,在.h文件name变量改写为了_name;在.m文件中@sythesize的写法也发生了变化。

如果通过方法self._name获取属性的值,xcode编译器会提示错误,其实这也就说明了,我们通常使用self.name实际使用的是studentnameget方法,同理nameset方法亦是如此。

 

接下来从内存管理来说明使用self.和不使用self的区别:

ViewController.h文件,使用Student类,代码如下:

<span class="lnum" style="margin: 0px; padding: 0px;">   1:  </span>#import <UIKit/UIKit.h>
   2:  @class Student;
<span class="lnum" style="margin: 0px; padding: 0px;">   3:  </span> 
   4:  @interface ViewController : UIViewController{
<span class="lnum" style="margin: 0px; padding: 0px;">   5:  </span>    
   6:      Student *_student;
<span class="lnum" style="margin: 0px; padding: 0px;">   7:  </span>}
   8:   
<span class="lnum" style="margin: 0px; padding: 0px;">   9:  </span>@property (nonatomic, retain) Student *student;
  10:   
<span class="lnum" style="margin: 0px; padding: 0px;">  11:  </span>@end

ViewController.m文件,代码:

<span class="lnum" style="margin: 0px; padding: 0px;">   1:  </span>#import <span class="str" style="margin: 0px; padding: 0px;">"ViewController.h"</span>
   2:  #import "Student.h"
<span class="lnum" style="margin: 0px; padding: 0px;">   3:  </span> 
   4:  @implementation ViewController
<span class="lnum" style="margin: 0px; padding: 0px;">   5:  </span>@synthesize student = _student;
   6:   
<span class="lnum" style="margin: 0px; padding: 0px;">   7:  </span>- (<span class="kwrd" style="margin: 0px; padding: 0px;">void</span>)didReceiveMemoryWarning
   8:  {
<span class="lnum" style="margin: 0px; padding: 0px;">   9:  </span>    [super didReceiveMemoryWarning];
  10:  }
<span class="lnum" style="margin: 0px; padding: 0px;">  11:  </span> 
  12:  #pragma mark - View lifecycle
<span class="lnum" style="margin: 0px; padding: 0px;">  13:  </span> 
  14:  - (void)viewDidLoad
<span class="lnum" style="margin: 0px; padding: 0px;">  15:  </span>{
  16:      [super viewDidLoad];
<span class="lnum" style="margin: 0px; padding: 0px;">  17:  </span>}
  18:   
<span class="lnum" style="margin: 0px; padding: 0px;">  19:  </span>- (<span class="kwrd" style="margin: 0px; padding: 0px;">void</span>) dealloc
  20:  {
<span class="lnum" style="margin: 0px; padding: 0px;">  21:  </span>    [_student release];
  22:      _student = nil;
<span class="lnum" style="margin: 0px; padding: 0px;">  23:  </span>    [super dealloc];
  24:  }

其它的方法没有使用到,所以这里就不在显示了。

ViewController.mviewDidLoad方法中创建一个Student类的对象

<span class="lnum" style="margin: 0px; padding: 0px;">   1:  </span>Student *mystudent = [[Student alloc] init];
   2:  self.student = mystudent;
<span class="lnum" style="margin: 0px; padding: 0px;">   3:  </span>[mystudent release];

这是相信有人会有疑问了,问什么创建student对象要这么复杂,似乎直接使用self.student = [[Student alloc] init]; 也没有问题,不加self有时也是挺正常的呀

接下来就需要从内存角度来分析它们之间的区别了:

1、加self的方式:

Student *mystudent = [[Student alloc] init];       //mystudent 对象 retainCount = 1;

self.student = mystudent;   //student 对象 retainCount = 2;

[mystudent release];  //student 对象 retainCount = 1;

retainCount指对象引用计数,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;容易造成内存泄露

由于objective-c内存管理是根据引用计数处理的,当一个对象的引用计数为零时,gcc才会释放该内存。

  转载: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];
}        
通过短时倒谱(Cepstrogram)计算进行时-倒频分析研究(Matlab代码实现)内容概要:本文主要介绍了一项关于短时倒谱(Cepstrogram)计算在时-倒频分析中的研究,并提供了相应的Matlab代码实现。通过短时倒谱分析方法,能够有效提取信号在时间与倒频率域的特征,适用于语音、机械振动、生物医学等领域的信号处理与故障诊断。文中阐述了倒谱分析的基本原理、短时倒谱的计算流程及其在实际工程中的应用价值,展示了如何利用Matlab进行时-倒频图的可视化与分析,帮助研究人员深入理解非平稳信号的周期性成分与谐波结构。; 适合人群:具备一定信号处理基础,熟悉Matlab编程,从事电子信息、机械工程、生物医学或通信等相关领域科研工作的研究生、工程师及科研人员。; 使用场景及目标:①掌握倒谱分析与短时倒谱的基本理论及其与傅里叶变换的关系;②学习如何用Matlab实现Cepstrogram并应用于实际信号的周期性特征提取与故障诊断;③为语音识别、机械设备状态监测、振动信号分析等研究提供技术支持与方法参考; 阅读建议:建议读者结合提供的Matlab代码进行实践操作,先理解倒谱的基本概念再逐步实现短时倒谱分析,注意参数设置如窗长、重叠率等对结果的影响,同时可将该方法与其他时频分析方法(如STFT、小波变换)进行对比,以提升对信号特征的理解能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值