// 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

减号方法

也叫对象方法

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

加号方法

也叫类方法、静态方法

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

方法传参

// 一个参数
- (void) funcname:inta

// 多个参数
- (void) funcname:inta and:intb

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

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

propterty

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

// 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,变量名 直接可以调用

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

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

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

- (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 之前非常常见

点表达式

p.age = 20;
// 等于 [p setAge:20]

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

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

static 关键字

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这种

前置声明

也叫不完全声明

// .h
@class ClassName

// .m
import "ClassName.h"

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

dealloc

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

// 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. 初始化实例变量
// Person.h
- (id)initWithName:(NSString*)nameValue age:intageValue;

// Person.m
- (id)initWithName:(NSString*)nameValue age:intageValue {
  // 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;
}

协议和代理

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

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

// 声明
@protocol nameDelegate<NSObject>

// 必须实现
@required

- (void) say();

// 可选
@optional

// ...

@end

定义两个类文件

// 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

使用

// 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];
  }
}
评论区域将在可见后加载…