Grammar
1.类定义
#import <Foundation/Foundation.h> $interface Fraction : NSObject { @protected: int numerator; int denominator; } -(void) print; -(id)initSetNum:(int) n over:(int) d; -(id)init; @end
#import "Fraction.h" #implementation Fraction -(void) print { NSLog(@"print"); } -(id)init{ self = [super init]; if (self != nil) { self->denominator = 1; self->numerator = 1; } return self; } -(id)set:(int)n over:(int) d { self->denominator = d; self->numerator = n; return self; }
2.访问权限
实例变量的作用域
@protected: 实例变量可被该类和子类中定义的方法直接访问。接口部分定义的实例变量是此作用域
@private: 只能被定义在此类中的方法直接访问。定义在实现部分的实例变量默认为此作用域
@public: 可被此类中的方法、子类或其他类直接方法(访问方法见下面点语法)
@package: 对于64位镜像,可以在实现改类的镜像中的任何地方访问此实例变量(不了解,没用过)
@property作用域
@property只在@interface中使用,是默认的@protected权限
方法的作用域
@protected,@private,@public,@package不适用实例方法,在@interface中定义的方法都是@public方法
私有方法
1.不在@interface中声明,直接写到@implemention里。
2.写在空分类中。
3.属性设置
@property, @synthesize
作用1:生成成员变量的get和set方法
@interface Fraction : NSObject @property int numerator, denominator; -(void)print; @end @implementation Fraction @synthesize numerator = _n, denominator = _d; -(void)print { self->_n = 12; self->_d = 20; } @end
#import <Foundation/Foundation.h> #import "Fraction.h" int main(int argc, const char* argv[]) { @autoreleasepool { Fraction *fraction = [[Fraction alloc] init]; [fraction setNumerator:10]; NSLog(@"numerator is %d", [fraction numerator]); fraction.numerator = 20; NSLog(@"numerator is %d", [fraction numerator]); } return 0; }
作用2:协助内存管理
attribute主要分三类:
- 读写属性:(readwrite/readonly)决定是否生成set访问器,默认为readwrite
- setter语义:(assign/retain/copy/strong/weak/unsafe_unretained)set访问器的语义,决定已何种方式对数据成员赋予新值,默认为assign
- 原子性:(atomic/nonatomic)是否是原子性访问,默认为nonatomic
readwrite: 生成setter/gettter方法(默认)
readonly: 只生成getter。@synthesize不会生成setter方法,所以不能和copy/retain/assign同时使用
assign: 简单赋值,不更改索引计数
retain: 释放旧的对象,将旧对象的值赋予输入对象,在增加输入对象的引用计数(+1)。此属性只能用于Objective-c对象类型,不能用于基本类型和Core Foundation对象(Core Foundation?此乃何物),因为他们没有引用计数
strong/weak/unsafe_unretained: xcode5加入的新属性,strong = retain,unsafe_unretained = assign,weak ~= assign,在引用计数为0时,对吧对象赋值为nil
copy: 建立一个引用计数为1的对象,然后释放旧对象。此属性只对实现了NSCopying的对象类型有效
atomic/nonatomic: setter和getter是不是原子操作,如果是atomic则在多线程情况下,setter和getter中不会被阻塞(切换线程)
4.类扩展
category(分类)
向类中增加方法,但不改变原有类实现,或找不到实现文件,category就可以发挥作用。
MathOps.h文件
#import "Fraction.h" @interface Fraction(MathOps) -(void)double; @end
MathOps.m文件
#import "MathOps.h" @implementation Fraction(MathOps) -(void)double { [self numerator] = [self numerator] * 2; } @end
extension(扩展)
extension是category的一个特例,也被称为匿名分类,作用是为类增加私有成员变量和方法。
只能在m文件中定义
#import "Fraction.h" @interface Fraction() { int maxNum; } @property int minNum; @end
protocol(协议)
即接口,只提供声明
@protocol NSCopying -(id)copyWithZone:(NSZone *)zone; @end
protocol中@required或默认方法一定要实现,@optional的方法不一定要实现
@protocol Drawing -(void)paint; //必须实现 -(void)erase; //必须实现 @optional -(void)outline; @required -(void)showDetail; @end
5.ARC内存管理
ARC(Automatic Reference Counting)自动引用计数(神马是引用计数自行脑补)。Xcode 4.2版本之后加入的新特性。Xcode4.2之前的内存管理要内存要小心的处理引用计数,retain,release,autorelease在代码中随处可见。
XCode4.2之后的ARC是在编译的时候由编译器在代码中添加retain,release,autorelease代码,程序要要做的就是开启ARC(默认开启)功能, 在@property属性参数中声明号strong,weak等属性就行了(定义变量时也可以用strong,weak等)。 开启ARC后不能使用retain,release,编译不通过。
@autorealeasepool
任何在@autoreleasepool{}中定义的变量都是autorelease的,在出@autoreleasepool{}作用域时,会对其中的变量做一次release操作。
Cocoa和IOS应用程序中也有这个@autoreleasepool{},也就是说Cocoa和IOS中的变量都是autorelease的,每帧循环后会对autoreleasepool中的对象做一次pop操作,把对象从autoreleasepool中删除,并做一次release。Objective-C Autorelease Pool 的实现原理这个介绍了ios中的autorealeasepool
6.selector
SEL 类成员方法的函数指针
@selector是查找当前类(含子类)的方法。
parent.h文件
#import <Foundation/Foundation.h> @interface SelectorDemo : NSObject { Sel _methodTest; } @property (nonatomic,assign) SEL methodTest; -(void)TestParentMethod; -(void)TestSubMethod; @end
parent.m文件
#import "SelectorDemo.h" @implementation SelectorDemo @synthesize methodTest = _methodTest; -(void) parentMethod { NSLog(@"parent method call success"); } -(void)TestParentMethod { if (_methodTest) { [self performSelector:_methodTest withObject:nil]; } } -(void)TestSubMethod { if (_methodTest) { [self performSelector:_methodTest withObject:nil]; } } @end
7.block
有参数带返回值的block
-(void)myThirdBlock { double (^myThirdBlock)(double,double) = ^(doube r1, double r2) { return r1 + r2; } double r3 = myThirdBlock(1.1, 2.2); NSLog(@"return value:%f", r3); } @end
block的注意点
- block内部可以访问外部变量
- 默认情况下,block内部不能修改外部的局部变量
- 给局部变量加上__block关键字,则这个局部变量可以在block内部进行修改
-(void)myFourBlock { int num = 4; void (^myFourBlock)() = ^{ num = 5; NSLog(@"return value:%d", num); } }