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