1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Person.h 声明
#import <Foundation/Foundation.h>
@interface Person : NSObject
- (void) funcname
+ (void) funcname
@end

// Person.m 实现
#import "Person.h"
@implementation Person
- (void) funcname {
NGLog(@"Hello OC");
}
+ (void) funcname {
NGLog(@"Hello OC");
}
@end

减号方法

也叫对象方法

  • 声明
1
- (void) funcname
  • 调用
1
2
3
4
// 实例化类
Person *p1 = [[Person allot] init];
// 然后再调用
[p1 funcname];

加号方法

也叫类方法、静态方法

  • 声明
1
+ (void) funcname
  • 调用
1
2
直接调用
[Person funcname];

方法传参

1
2
3
4
5
// 一个参数
- (void) funcname:(int)a

// 多个参数
- (void) funcname:(int)a and:(int)b

方法名包括冒号,甚至可以声明下面的方法

1
- (void):(int)a :(int)b

propterty

生成get、set方法、属性变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// Person.h
#import <Foundation/Foundation.h>
@interface Person : NSObject
{
// 可以不写
int _age;
NSString *_name;
}

@property(nonatomic, assign) int age;
@property(nonatomic, assign) NSString *name;

- (void) say();

@end

// Person.m
#import "Person.h"
@implementation Person

// 可以不写
@synthesize age = _age;
@synthesize name = _name;

- (void) say() {
NGLog(@"my name is %s", _name);
NGLog(@"my name is %s", self.name); // self.name等于[self name]
}

@end
  • 参数1

  • natomic 原子属性(线程安全),需要消耗大量资源

  • nonatomic 非原子属性(非线程安全),适合内存小的设备

  • 参数2

  • assign 直接赋值

  • strong 强引用,销毁后指向的内存数据也会被销毁

  • weak 弱引用

  • 参数3

  • readonly只能读取(只生成get方法)

set方法是setAge,变量名第一个字母大写
get方法是age,变量名
直接可以调用

1
2
Person *p = [[Person alloc] init];
[p age]

使用@propterty后也可以定义setOne方法来进行重写set、get方法

注意自动生成的get方法可能会造成泄漏,可以改为以下写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- (void)setName:(char*)nameValue {
// 自动生成的是 name = nameValue;
if(nameValue) {
if(name != nameValue) {
// 释放空间
free(name);
// 置空(好像可以不写)
name = NULL;

// 获取nameValue的长度
int len = StrLength(nameValue) + 1;
// 设置长度
name = (char*) malloc(len);
// 赋值
strcpy(name, nameValue);
}
}
}

synthesize

合成指令,在 Xcode 4.5 之前非常常见

点表达式

1
2
3
4
5
p.age = 20;
// 等于 [p setAge:20]

NGLog(@"age = %d", p.age);
// 等于 [p age];

点表达式如果做左值,就是调用set方法,如果做右值则是调用get方法

static 关键字

1
2
3
4
5
6
7
8
9
10
11
12
void func() {
static int a = 0;
int b = 0;
a++;
b++;
}

// 如果多次调用
func(); // a = 1 ,b = 1
func(); // a = 2, b = 1

// static int a = 0; 只会被执行一次,把a放入静态存储区

self 关键字

类似this这种

前置声明

也叫不完全声明

1
2
3
4
5
// .h
@class ClassName

// .m
import "ClassName.h"

告诉编译器,这是个类,但类中有什么方法不会加载进来
可以直接在.h文件中导入ClassName.h,但运行效率低,不推荐

dealloc

析构函数,用来释放内存空间
需要在编译设置Build Phases > Compile Sources > 相应的文件加上-fno-objc-arc表示手动维护内存

1
2
3
4
5
6
7
8
9
10
11
// Person.m
- (void) dealloc {
[super dealloc]
NGLog(@"dealloc function called");
}

// main.m
Person *p = [[Person alloc] init];
// 手动释放
[p release];
// 释放后dealloc会被自动调用

现在有arc机制,自动维护内存

初始化传参

首先需要自定义一个初始化函数,函数名必须以init开头,并遵循以下规则

  1. 判断参数有效性
  2. 初始化父类
  3. 初始化实例变量
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Person.h
- (id)initWithName:(NSString*)nameValue age:(int)ageValue;

// Person.m
- (id)initWithName:(NSString*)nameValue age:(int)ageValue {
// 1
if(!nameValue || ageValue > 120) {
return nil;
}

// 2
self = [super init];
if(!self) {
return nil;
}

// 3
self.name = [[NSString alloc]initWithString:nameValue];
if(!self.name) {
self = nil;
return nil;
}
self.age = ageValue;
}

协议和代理

协议有约束作用,只声明不实现,类似抽象类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// nameDelegate.h
#import <Foundation/Foundation.h>

// 声明
@protocol nameDelegate<NSObject>

// 必须实现
@required

- (void) say();

// 可选
@optional

// ...

@end

定义两个类文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
// Animal.h
#import <Foundation/Foundation.h>
#import "nameDelegate.h"
@interface Person : NSObject<nameDelegate>

@property(nonatomic, assign) id<nameDelegate> delegate;

- (void)sayNyan {
NGLog(@"喵喵喵");
// 通知人类我喵喵喵了
[self.delegate say];
}

@end

// Person.h
#import <Foundation/Foundation.h>
#import "nameDelegate.h"

@class Animal

@interface Person : NSObject<nameDelegate>

@property(nonatomic, strong) Animal *nyanko

@end

// Person.m
import "Person.h"

@implementation Person

- (id)init {
self = [super init];
if(!self) {
return nil;
}

self.nyanko = [[Animal alloc] init];
if(!self.nyako) {
self = nil;
return nil;
}

// 代理 ???
self.nyanko.delegate = self;
return self;
}

// 实现协议
- (void)say {
NGLog(@"它喵喵喵了");
}

@end

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
// main.m
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Animal.h"

int main(int argc, const char * argv[]) {
@autoreleasepool {
// 造猫
Person * cat = [[Person alloc] init];
// 让她叫
[p.nyanko sayNyan];
}
}