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);
}
}