Archive for the ‘01 – 基础信息’ Category.

retain和copy的区别

原来简单解释过属性定义(Property) ,并且提起了简单的retain,copy,assign的区别。那究竟是有什么区别呢?

assign就不用说了,因为基本上是为简单数据类型准备的,而不是NS对象们。

Retain vs. Copy!!

  • copy: 建立一个索引计数为1的对象,然后释放旧对象
  • retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1

那上面的是什么该死的意思呢?

Copy其实是建立了一个相同的对象,而retain不是:

比如一个NSString对象,地址为0×1111,内容为@”STR”

Copy到另外一个NSString之后,地址为0×2222,内容相同,新的对象retain为1,旧有对象没有变化

retain到另外一个NSString之后,地址相同(建立一个指针,指针拷贝),内容当然相同,这个对象的retain值+1

也就是说,retain是指针拷贝,copy是内容拷贝。哇,比想象的简单多了…

数据类型/对象类型介绍(1)NSString

字符串是程序设计最常用的数据类型之一了。在Mac/iPhone编程中,苹果为我们提供了一个不同的字符串类型NSString。有别与普通的String为数据类型,NSString其实是一个对象类型。NSString是NSObject(Cocoa Foundation的基础对象)的子类,所以具有NSObject的所有特性,好的和好的… ….

小常识:
NS是Cocoa类对象类型的前缀,来源于史蒂夫-乔布斯被苹果开除那段时间建立的公司NeXT.
@是Cocoa元素的前缀,很多地方我们会看到,比如接下来...

1, 创建一个NSString对象

简单方法:

NSString *aString = @"我是个NS字符串!";  //除了引号外加@, 没别的区别

*上面的不需要操心内存管理哟~

复杂一点儿:(需要内存管理的)

NSString *aString = [[NSString alloc] initWithFormat:@"这也是个NS字符串!"];

*initWithFormat是其中一个初始化方法,常用的还有

//从一个文件读取需要的内容
- (id)initWithContentsOfFile:(NSString *)path encoding:(NSStringEncoding)enc error:(NSError **)error
//从一个地址读取需要的内容
- (id)initWithContentsOfURL:(NSURL *)url encoding:(NSStringEncoding)enc error:(NSError **)error

*以上方法得到的NSString的retain值为1,所以记得release掉阿~~

2,使用一个NSString对象

NSString *aString = @"This is a NSString";
 
NSLog(aString);   //在控制台输出信息,该函数方法需要一个NSString对象作为参数
 
NSLog("这样不会好使的");
 
NSLog(@"这样就会好使拉~");

再比如设置一个UIView的标题:

[UIView setTitle:aString];
 
[UIView setTitle:@"标题"];
 
UIView.title = aString;

3,释放NSString

[aString release]; //对象将被系统释放掉咯

*记得不要释放直接用 = @”xxx” 的NSString对象哟,系统会管的~

4,快速使用一个NSString

NSLog([NSString stringWithFormat:@"一个NS字符串"]);

//这种快速方法返回的是一个retain为1,autorelease的对象,不需要操心它的内存管理

5,常用方法

我喜欢NSString的地方就在于很多方法非常方便,比如:

nString = [aString substringToIndex:4]; //nString将得到aString中的前四个字符

6,小结

暂时能记起来的就这么些了,有机会再补充,希望大家NS的愉快~

iphone程序的开始画面设置

* iPhone软件启动后的第一屏图片是非常重要的往往就是loading载入中的意思。设置它说来也简单,但是却无比重要

只需要在resource里面将你希望设置的图片更名为Default.png,这个图片就可以成为iPhone载入的缺省图片

屏幕快照 2009-07-25 上午10.50.19

64位编程:整数/小数

A 对应64位编程的时候,

对于整数应使用NSInteger和NSUInteger,而非int

对于小数应使用CGFloat,而非float

NSInteger其实是一个自动定义,在32位中为int,而64位中为long。CGFloat的原理类似

误释放对象

W 问题一:

value = [array objectAtIndex:n]; //得到一个数组中的对象
[arry removeObjectAtIndex:n]; //卸载那个对象

因为value得到了那个对象,但是由于另外一个拥有者release了该对象,所以其实value现在成了摇摆指针(无效数据)

问题二:

myArray = [NSArray array];
...
[myArray release];

NSArray返回的是一个自动释放对象,不仅myArray不应该在一段时间后release,而应该在适当的时候先retain,以防止该array被系统误释放。

问题三:

rocket = [rocketLauncher aRocket];
[rocketLauncher release];

和array这种数据收集类对象一样,如果我们得到了一个类的子对象而不retain它,那么在原父类被释放的时候,这个rocket其实也会失去其意义。

对autorelease的误解

A Cocoa的内存管理分为 索引计数法(Reference Counting/ Retain Count)和 垃圾收集法(Garbage Collection)。而iPhone上目前只支持前者,所以autorelease就成为很多人的“捷径”。

但是!autorelease其实并不是“自动释放”,不像垃圾收集法,对对象之间的关系侦测后发现垃圾-删除。但是autorelease其实是“延后释放”,在一个运行周期后被标记为autorelease会被释放掉。

切记小心使用autorelease,理解autorelease,防止在你还需要该对象的时候已经被系统释放掉了。

一些iPhone的系统目录

D

得到Document目录:

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];

得到temp临时目录:

NSString *tempPath = NSTemporaryDirectory();

得到目录上的文件地址:

NSString *文件地址 = [目录地址 stringByAppendingPathComponent:@"文件名.扩展名"];

Interface Builder参与的内存管理问题

I 要点:

  • 如果一个变量在类中被定义为了 IBOutlet 那么你无需对其进行实例化,xib载入器会对其初始化。
  • 如果一个变量在类中被定义为了 IBOutlet 那么你必须负责将其释放。xib载入器不会帮忙的… …

*切不要初始化两回,内存会溢出,而且对象锁定也会出错。

关于索引计数(Reference Counting)的问题

M *retain值 = 索引计数(Reference Counting)

  • NSArray对象会retain(retain值加一)任何数组中的对象。当NSArray被卸载(dealloc)的时候,所有数组中的对象会被执行一次释放(retain值减一)。不仅仅是NSArray,任何收集类(Collection Classes)都执行类似操作。例如NSDictionary,甚至UINavigationController。
  • Alloc/init建立的对象,索引计数为1。无需将其再次retain。
  • [NSArray array]和[NSDate date]等“方法”建立一个索引计数为1的对象,但是也是一个自动释放对象。所以是本地临时对象,那么无所谓了。如果是打算在全Class中使用的变量(iVar),则必须retain它。
  • 缺省的类方法返回值都被执行了“自动释放”方法。(*如上中的NSArray)
  • 在类中的卸载方法“dealloc”中,release所有未被平衡的NS对象。(*所有未被autorelease,而retain值为1的)

NSString的内存管理

CS193P的笔记上有如下实例:

aString = @"I am a string that 2 years old, man!";

这种情况下,字符串储存和管理由系统做,我们不用操心。

aString = [NSString stringWithFormat:@"I am a string that %d years old, man!",2];

第二种情况下,我们需要去retain和release这个字符串,系统不管。