现在的位置: 首页 > 综合 > 正文

OC语法学习小结

2013年08月22日 ⁄ 综合 ⁄ 共 4740字 ⁄ 字号 评论关闭

1、定义类:
@interface 类名 : 父类
@end

2、使用:(冒号)表示继承一个类
Student : NSObject

3、使用()定义一个Catagory(类别)

* 作用:在不改变原有类结构的基础上,扩展原有类的方法(不能扩展属性),但不建议重载原有类的方法

* 开发工具默认生成的文件为:类名+Catagory名称

* Catagory可以写在单独的文件中,也可以写在原有类的文件中,如何写根据需求来决定。


4、使用<>表示实现一个Protocol(协议),如需实现多个协议,将协议名以逗号分隔都写在括号中即可

*可以理解为java中的接口,但不同的是,实现类编译器不强制实现Protocol中定义的所有接口

* 在方法签名上标识:@required,从字面上理解实现类必须实现该方法,其实写与不写一样的效果。也是默认的

* 在方法签名上标识:@optional,表示实现类对该方法的实现,是可选的。

  
5、属性的访问权限

* private : 只有类内部可以访问

* protected : 类内部和子类可以访问(默认)

* public : 访问没有限制

例:

// 定义

@interface Student : NSObject {

@private int _age;

@protected int _no;

@public float _height;

}
@end

// 使用
Student *stu = [[[Student alloc]init]autorelease];
stu->_height = 20;// 直接读写属性的值,开发当中一般不建议这么做。违背了面向对象的开发原则-》封装性

6、属性的定义与封装
// in Student.h
@interface Student : NSObject {

// 1. 定义属性,默认访问权限是@protected的,只有自已和子类可以直接访问

int _age;// OC语法中建议属性名前面加上下划线,以和参数名区分

int _no;

}

// 2.提供属性对外读写方法的声明,供外界调用。OC创建属性读写方法的命名规则是为,set方法: set+属性名,get方法:属性名
// 声明age的get和set方法
- (int)age;
- (void)setAge:(int)age;

// 声明no的get和set方法
- (int)no;
- (void)setNo:(int)no;
@end

// in Student.m 实现头文件中的方法
#import "Student.h"// 导入头文件
@implementation Student

// 实现头文件中的方法
- (int)age {
// age的getter方法

return _age;

}

- (void)setAge:(int)age {// age的setter方法

_age = age;

}

- (int)no {

return _no;

}

- (void)setNo:(int)no {

_no = no;

}
@end

7、使用@synthesize自动生成属性getter和setter方法的实现,同时会生成一个下划线(_)+属性名的成员变量。需要和@property配合使用。例:
@implementation Student

@synthesize age;// 这一句顶下面的get和set方法,由@synthesize自动生成
/*
* 1. 如果显示实现了get方法,@synthesize会自动生成属性的set方法实现
* 2. 如果显示实现了set方法,@synthesize会自动生成属性的get方法实现
* 3. 如果即没有实现get方法,也没有实现set方法,则@synthesize会自动生成属性的get和set方法实现
*/
- (int)age {
// age的getter方法

return _age;

}

- (void)setAge:(int)age {// age的setter方法

_age = age;

}

@end

注:在xcode4.5以后的编译环境中,不需要写@synthesize声明生成属性的get和set方法实现。只需要在头文件中用@property定义即可自动在.m文件中生成相应属性的get和set方法实现


8、使用@property声明一个属性,编译器会自动生成该属性的getter和setter方法的声明

在xcode4.5以后版本的编译器环境中,会自动在.m文件中生成该属性getter和setter方法的标准实现,不需显示声明用@synthesize来生成属性的getter和setter方法实现。


9、@property属性参数
1> nonatomic : 多线程环境下,不需要线程保护(读写时不加锁), 
  atomic : (默认)多线程环境下需要线程保护(读写时加锁).
2> readonly : 表示在.m文件中只生成属性的getter方法的实现
  readwriter : 表示在.m文件中生成属性的getter和setter方法的实现(默认)
3> retain : 表示调用该属性的setter方法时,先release旧的值,再retain新的值。一般声明的成员变量是NSObject的子类才会添加该参数
  assign : 生成标准的getter和setter方法实现(默认),直接给属性赋值
4> getter= : 表示自定义属性生成的getter方法名称
  setter= : 表示自定义属性生成的setter方法名称

10、方法调用
* [实例对象 方法名:参数列表]
* [类名 方法名:参数列表]
例:
Student *stu = [[[Student alloc]init]autorelease];
[stu setAge:22 andNo:10];// 调用实例方法

[Student initWithAge:20];// 调用静态方法

11、点(.)语法
Student *stu = [[[Student alloc]init]autorelease];
stu.age = 20;
// 相当于调用了对象的setAge方法(写)
int age = stu.age;// 相当于调用了对象的getAge方法(读)

12、self关键字
相当于java中的this,不同的是self在不同的环境下,作用也不同。在实例方法中self可以当该对象使用,在静态方法中,self可以当类对象使用。
如:
- (void)age {
   return self.age;// 这里self是实例对象本身
}

+ (id)newInstace {

//Student *stu = [[[Student alloc]init]autorelease];

Student *stu = [[[self alloc]init]autorelease];// 这一句和上一句代码的效果是等效的,而在java语法是不允许this出现在静态方法中的

return stu;
}
  

13、@class : 在头文件中声明一个类的存在

为了提高效率,在只需要知道类的存在的情况下,不需要导入某个类的头文件。

// #import "Book.h"
@class Book;
// 不需要导入Book.h头文件,在.m文件真正使用的时候再导入
@interface Student : NSObject
@property Book *book;
@end

14、@protocol : 在头文件中声明一个协议的存在

目的和@class一样


15、^ : 定义一个Block类型,与标准C语法中指向函数指针类型的写法非常相似
如:定义一个sum的Block类型,返回值为int,有两个int形参
int (^sum) (int, int) = ^(int a, int b) {

return a + b;

}; 

16、#import : 用于导入一个类的头文件
#pragma mark : 写方法的注释
#pragma mark - : 方法注释分组
+ : 声明或定义一个静态方法
- : 声明或定义一个实例方法

17、方法定义(一个冒号代表一个参数,冒号也是属性方法的一部份)
方法类型 (返回值类型)方法名称[参数列表] {(一个冒号代表一个参数,冒号也是属性方法的一部份)
// 方法体
}

* 实例方法,方法名: sumAge:andNo:
- (int)setAge:(int)age andNo:(int)no {
// 在这里插入代码逻辑
}

* 静态方法
+ (id)initWithAge:(int)age {
// 在这里插入代码逻辑
}
注:
* 实例方法通过类的实例对象访问
* 静态方法通过类名或self访问

18、内存管理
 1> 凡是从NSObject中继承的类都需要自己管理内存,在OC语法中,创建的任何一个对象都拥有一个引用计数器,第一次创建的时候这个引用计数器为1,当引用计数器的值为0时,该对象会被销毁。内存管理涉及到以下接口:
  * release : 对象的引用计数器减1
  * retain : 对象的引用计数器加1
  * retainCount : 获取对象当前引用计数器的数量
 
  对象生命周期回调接口:
  * init : 对象的默认构造方法,如果自定义构造方法用于初始化成员变量时,必须先调用父类的构造方法,并判断获得的对象是否为nil,再初始化成员变量。
  如:- (void)initWithAge:(int)age {

     if ( self = [super init] ) {

         _age = age;

 }

 return self;

 }
 
  * dealloc : 对象销毁时,系统会自动调用该方法,通常在该方法中释放内存或其它资源。在重写dealloc方法时,注意在代码最后面调用父类的dealloc方法,用于释放内存等相关资源。

 如:

- (void)dealloc {

 [_book release];// 释放成员变量

 [super dealloc];

 }
 
 2> 不需要管理内存的对象
  * 基本数据类型
  * 系统自带的类调用自己的静态方法创建的对象,是自动释放内存的,不需要管理
 
 3> 内存管理原则
  只有向对象发送了alloc,retain,copy,new消息才有必要做release操作
  * 谁alloc,retain,copy,new谁release
  * 谁创建谁释放(release)
  * 谁没有alloc,retain,copy,new,你就不要做release操作
 
 4> 自动内存管理(由autoreleasepool管理)
  在创建对象的同时,调用autorelease方法,会将该对象的一个引用自动存放到最近创建的一个自动释放释放池中。以后该对象就不需要手动来release操作,徐非做了retain,copy等修改了引用计数器的操作。当自动释放池被销毁时,会向池子中所有对象发送一个release消息,池子中的所有对象的引用计数器此时会减1,只有当池子中的引用计数器为0时,该对象才会被彻底销毁。不是说只要将对象交给自动释放池了,池子被销毁,池子中的所有对象就一定会被销毁。
 

 如:@autoreleasepool {

 Student *stu = [[[Student alloc] init]autorelease];// 此时stu对象将放到这个大括号中的自动释放池子中
 
  [stu retain];// 如果加了这一句,此时stu的引用计数器为2,这时候如果在池子销毁前没有向对象发送release消息,就算池子销毁,该对象也还是会造成内存泄露
 
  } // 程序执行到此处,代表自动释放池被销毁,意味着池子中的所有对象都会接到一个release消息

19、OC中的类似Java的toString方法
Student *stu = [[[Student alloc]init]autorelease];
NSLog(@"%@",stu);// 默认打印的是stu对象的内存地址

* 重写父类的description方法,可自定义打印对象的信息
- (NSString *)description {
   NSLog(@"age is %i",_age);

}

抱歉!评论已关闭.