objective-c基础学习1(原版参考:http://cocoadevcentral.com/d/learn_objectivec/)

2014-09-22  文晶 


id myObject = [NSString string];

1、id类型---myObject可以是任意类型的对象

2、NSString* myString = [NSString string];

 备注:NSString类型的变量了,如果我们在这个对象上调用NSString 类型对象不支持的方法,编译器就会发出警告

 注意:在对象类型的右面有一个星号(*),在Objective-C中,所有的对象变量 都是指针类型。id类型已经被预定义为指针类型,所以不需要加一个星号。

 

3、创建对象两种方法

1)NSString* myString = [NSString string];这是一种更加自然的方式,通过这种方式可以创建一个自动释放(autoreleased)对象

2)NSString * myString =[[NSString alloc] init]

这是一个嵌套防范的调用,第一个是NSString 类本身alloc方法调用,这是一个相对底层的调用,作用是:分配内存及实例化一个对象,第二个是调用新创建的对象的init方法,做对象的初始化设置工作。

NSNumber* value = [[NSNumber alloc] initWithFloat:1.0]; init方法的另一种版本,带有输入参数

4、内存管理

1)编写程序时可以选择允许 垃圾回首--不是特别复杂的情况下,可以不用考虑内存管理

2)通过手工alloc的方式创建的对象,使用之后需要release这个对象

3)不能手工(release)的释放一个自动释放(autoreleased)的对象--造成应用程序崩溃

例子:
//string1 将被自动释放
NSString* string1 = [NSString string];

//必须在用完后手工释放
NSString* string2 = [[NSString alloc] init];

 [string2 release];

自动释放对象---可以认为当前函数结束的时候被自动释放

5、设计类接口

objective-c的语法中:创建一个类非常简单。

一个类通常为两部分:类的接口 、 类的实现

类的接口(interface):存放在ClassName.h的文件中

类的实现:存放在ClassName.m的文件中,包含方法的世纪实现代码,通常还定义了客户类不能访问的私有(private)方法

1)接口例子:

Photo.h:

#import <Cocoa/Cocoa.h>

 
@interface Photo : NSObject { NSString* caption; NSString* photographer;

}

@end
import:倒入应用程序的基本类
interface:类的声明“:”冒号后面时父类
花括号里面声明了两个实例变量:caption和photographer。都是NSString 类型,实例变量可以是任何对象类型,包括id类型。
@end符号结束类的声明。

1.1)添加get/ set方法

1.1.1)get

给实例变量添加一些获取器(getter)

#import <Cocoa/Cocoa.h>

@interface Photo : NSObject { NSString* caption; NSString* photographer;

}

- caption;
- photographer;

@end

 

备注:objective-c中通常省略get方法的“get”方法前缀,如上例

减 号(-)表明该方法是一个实例方法。

加号(+),则表明该方法 是一个类(static)方法。

编译器会默认一个方法的返回值是一个id类型的对象,所有的输入参数也默认是id 类型。上述代码在技术上是正确的,但是我们一般不这样写,我们需要给这些方法指定 返回值类型。如下

#import <Cocoa/Cocoa.h>

@interface Photo : NSObject { NSString* caption; NSString* photographer;

}
- (NSString*)caption;

- (NSString*)photographer;

@end

1.1.2)setter

#import <Cocoa/Cocoa.h>

@interface Photo : NSObject { NSString* caption; NSString* photographer;

}

-  (NSString*)caption;

-  (NSString*)photographer;

-  (void) setCaption: (NSString*)input;

-  (void) setPhotographer: (NSString*)input;

@end

设置器不需要有返回值,所以我们指定返回值是void。



 2)类实现

实现获取器/设置器(getter/setter)

#import “Photo.h"

@implementation Photo

-  (NSString*) caption { return caption;

}

-  (NSString*) photographer { return photographer;

}

-  (void) setCaption: (NSString*)input {

[caption autorelease];

caption = [input retain]; }

-  (void) setPhotographer: (NSString*)input {

[photographer autorelease];

photographer = [input retain];

}

@end

设置器需要处理两个变量,第一个时当前引用的对象,第二个输入新对象。

输入新对象前需要进行垃圾回收

在带有垃圾回收机制的环境中,可以直接直接设置成新的值:如下所示

- (void) setCaption: (NSString*)input

 {

caption = input;

 }

不能使用垃圾回收时需要手动的释放旧的对象retain新的对象,释放对象的引用有两种方式:

release:立刻释放对象的引用

autorelease:过会释放,但实际引用一直存在直到当前方法结束(除非特别干预)

3 init方法

init方法用来给实例化变量设置初始化值

- (id) init
{

if ( self = [super init] ) {//将[super init]的结果赋值给self。

[self setCaption:@"Default Caption"];

[self setPhotographer:@"Default Photographer"]; }

return self;

}

备注:super 父类做初始化操作,if校验在设置初始值前验证父类初始化是否成功。

4 dealloc

作用:从内存中删除对象时调用,在这个方法中释放所有对象的实例变量

‐ (void) dealloc {

[caption release];

[photographer release];

[super dealloc];

}

备注:1、释放变量时不需要使用autorelease,因为标准的release更快一些

2、super dealloc 要求父类做清理工作,如果没有这句对象就不会被从内存中删除,造成内存泄漏。

3、当启用垃圾回收机制时,对象的dealloc 方法不会被调用,需要实现一个finalize方法来替代它

6 内存管理

objective-c内存管理是基于引用计数的。释放内存工作由运行环境完成。

分配分(alloc)对象,保留(retain)的对象都需要发送release消息释放内存。如果alloc一次后又retain一次则需要release两次才能释放该对象的内存。



创建对象通常只有两个原因:

1、作为实例变量保留

2、在函数内部作为临时变量使用

回收规则:

1、大多数情况下,一个实例变量的设置器(setter)会自动释放(autorelease)原来引用的对象,同时保留(retain)新的。你只需要保证在dealloc函数中释放 (release)了它就行了。

2、如果你是通过alloc或者copy创建了一个对象,在函数结尾的地方给它发送一个release或者autorelease消息就行了。如果你是通过其它方式创建的对象,就什么 也别做。

下面是第一个例子,管理实例变量:

-  (void) setTotalAmount: (NSNumber*)input {

[totalAmount autorelease];

totalAmount = [input retain]; }

-  (void) dealloc {

[totalAmount release];

[super dealloc];

}

下面是另外一个例子,关于本地引用。我们只需要释放通过alloc创建的对象就行 了:

NSNumber* value1 = [[NSNumber alloc] initWithFloat:8.75]; NSNumber* value2 = [NSNumber numberWithFloat:14.78];

// only release value1, not value2

 [value1 release];

下面是一个组合例子,将一个本地引用设置给实例变量:

NSNumber* value1 = [[NSNumber alloc] initWithFloat:8.75]; [self setTotal:value1];

NSNumber* value2 = [NSNumber numberWithFloat:14.78]; [self setTotal:value2];

[value1 release];

注意,不论你是不是把本地引用当成实例变量一样赋值,管理它们都是完全相同的。 你不必考虑设置器(setter)是如何实现的。

如果你理解了这些,你就理解了关于Objective-C内存管理中90%你需要知道的内容。

7 日志记录

Objective-c中用于日志输出到控制台的方法是:NSLog()函数,

%@符号代表一个对象

例子:NSLog(@“hello world”);

NSLog ( @"The current date and time is: %@", [NSDate date] );

8 属性(Properties)

属性是objective-c的一个特性,允许我们自动生成访问器,同时还有其它方面的好处。如下代码片段对比。

之前的代码看上去是这样的:

#import <Cocoa/Cocoa.h>

@interface Photo : NSObject { NSString* caption; NSString* photographer;

}

-  (NSString*) caption;

-  (NSString*) photographer;

-  (void) setCaption: (NSString*)input;

-  (void) setPhotographer: (NSString*)input;

@end

用属性改写后的代码看上去是这样的:

#import <Cocoa/Cocoa.h>

@interface Photo : NSObject { NSString* caption; NSString* photographer;

}
@property (retain) NSString* caption; @property (retain) NSString* photographer;

@end

@property是Objective-C语言的一个指令,通过它声明属性。带括号 的”retain”指示设置器(setter)要保留输入值,该行后面的是指定属性的类型以 及名称。

下面我们看看这个类的实现部分:

#import "Photo.h"


@implementation Photo

@synthesize caption;

@synthesize photographer;

- (void) dealloc {

[caption release];

 [photographer release];

 [super dealloc];

}

@end

@synthesize 指令为主动为我们生成setter和getter,我们只需要实现dealloc方法进行释放即可。

注意:只有访问器不存在的时候,@synthesize才会自动生成访问器,所以即使用@synthesize声明了一个属性,仍然可以自定义getter 和setter,编译器会只会自动生成我们没有自定义的方法。

9 Nil上调用方法

objective-c  中的nil对象的作用等同于其它语言中的null,不同的地方在于,在nil上调用方法不会导致程序崩溃或抛出异常。

调用nil对象的方法并且改方法有返回值的话,就会得到一个nil返回值。

我们也可以用它来稍微改进一下我们的dealloc方法:

- (void) dealloc
{

self.caption = nil;

self.photographer = nil;

 [super dealloc];

}


可以这样做是因为当我们将nil赋值给一个实例变量,设置器(setter)会释放旧对 象并且保留(retain)nil对象。这种做法对于dealloc来说更好一些,因为这样做 避免了让变量指向一个随机的数据,而这个数据又恰好是另外一个对象。

注意,我们在这里使用了self.<var>语法,这表示我们使用的是setter,它会进 行内存管理。如果我们仅仅是直接设置值,像下面这样,那就会产生内存泄露:

// incorrect. causes a memory leak.
// use self.caption to go through setter caption = nil;


caption = nil;

10 类目(Category)

类目是objective-c中最有用的一个特性,踏允许你为已经存在的类添加一些方法而不用子类化该类,也不需要了解该类的实现细节。

作用:可以给一个内建的类对象添加方法,例如给NSString类型增加一个方法判断是不是一个url实现如下:

下面是一个实现。切记,这不是很好的检查URL的方法。我们只是为了说清楚类目 的概念。

#import "NSString-Utilities.h" @implementation NSString (Utilities)

- (BOOL) isURL {

if ( [self hasPrefix:@"http://"] ) return YES;

      else
         return NO;
}

@end

现在,你可以使用NSString的这个方法了,下面的代码会在控制台打印“string1 is a URL”:

NSString* string1 = @"http://pixar.com/"; NSString* string2 = @"Pixar";

if ( [string1 isURL] )
NSLog (@"string1 is a URL");

if ( [string2 isURL] )
NSLog (@"string2 is a URL");   


与子类不同,你不能通过类目来添加实例变量。但是你能通过类目重写(override) 类中已经存在的方法,当然,重写的时候要特别小心。

记住,当你通过类目更改一个类的时候,这个更改会影响你这个应用程序中所有这 个类的实例。

 

 

 

 

 



 

 



 

 



 

 

 



 

 

 
 

 



 

 

388°/3881 人阅读/0 条评论 发表评论

登录 后发表评论