- 值传递:基本数据类型的变量之间的数据传递
//值传递不会改变变量的值 void func(int a) { a = 4; } int main(int argc, const char * argv[]) { int a = 8 ; func(a); printf("%d",a);//答案为8 return 0; }
2. 指针类型之间的地址传递
//地址传递会改变变量的值 void func(int *a) { *a = 4; } int main(int argc, const char * argv[]) { int a = 8 ; func(&a); printf("%d",a);//答案为4 return 0; }
3. 全局变量static和extern
1)static修饰的全局变量作用范围为定义变量的文件,变量存储在静态区,生命周期与程序生命一致;
2)extern只能声明变量,使作用范围扩大到整个程序文件,生命周期与程序生命一致;
4.代理设置模式的数据传值
代理模式是为了解决程序的低耦合,高内聚而产生,比如:
1)A对象做不了的事情,B对象来帮A做;
2)B对象想监听A对象的行为;
3)当A发生一些事情, 想通知B对象的时候
//A设计协议 @protocol testViewDelegate @optional -(void)outPut:(NSString *)theTitle; @end //B遵守协议
... //B实现协议方法
...
5. 通过系统通知传值
//先发布通知 /* name:通知名称 object:谁发出通知 nil代表匿名发布 */ [[NSNotificationCenter defaultCenter] postNotificationName:@"note" object:nil]; //监听通知 //方式一: /* Observer:谁观察通知 selector:监听到通知,就会调用这个方法 name:通知名称 object:谁发出通知nil代表监听所有 */ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reciveNote) name:@"note" object:nil]; //方式二: /* name:通知名称 object:谁发出通知 queue: 确定Block在哪个线程调用 队列,传入nil,block就会直接运行在发布通知线程中 usingBlock:只要监听到通知,就会自动调用这个block */ _observer = [[NSNotificationCenter defaultCenter] addObserverForName:@"note" object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) { NSLog(@"%@",self); NSLog(@"%@",[NSThread currentThread]); NSLog(@"调用了block:监听到通知"); }];
//方式三
//userInfo表示传入的数据
[[NSNotificationCenter defaultCenter] postNotificationName:@"note" object:nil userInfo:nil];
6.通过的block传递(此项重点颇多)
6.1 Block声明
// 声明:返回值(^block变量名)(参数) void(^block)();//(无返回值无参数)
6.2 Block定义
// 定义 // 方式一: void(^block1)() = ^(){ NSLog(@"调用block1"); }; // 调用Block,就会去查看下Block保存代码 block1(); // 方式二:block如果没有参数,可以省略() // void(^)() void(^block2)() = ^{ }; // 方式三:block定义中,返回值可以省略 // 类型:int(^)() int(^block3)() = ^int{ return 2; }; //在Xcode中的快捷键是inline
6.3 Block类型
6.3.1 是对象
6.4 Block作用
6.4.1 保存代码块
6.4.2 Block:在一个类中定义,在另一个类中调用(常用), -> 传值
//在A类中定义一个block属性 @property (nonatomic ,strong) void(^block)(); //在B类中赋值 // 打电话 CellItem *item = [[CellItem alloc] init]; item.title = @"打电话"; item.block = ^{ NSLog(@"打电话"); }; //在B类方法中使用 if (item.block) { item.block(); }
6.4.3 传值:
A -> B 顺传:定义属性
B -> A 逆传:代理(block替换代理)
//为了替代代理 //在B类中声明block属性 @property (nonatomic ,strong) void(^valueBlock)(NSString *value); //同时在B类中使用,把值传递出去 - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { if (_valueBlock) { _valueBlock(@"123"); } } //在A类中定义block(首先拿到B类就能拿到B类传出去的值) ModalViewController *modalVc = [[ModalViewController alloc] init]; modalVc.valueBlock = ^(NSString *value){ NSLog(@"接收到%@",value); };
6.5 block的变量传递
6.5.1 默认局部变量在block中 是值传递
6.5.2 如果局部变量被static,__block,那么都是指针传递
6.5.3 全局变量.也是指针传递
6.6 block作为参数使用
// 计算 - (void)calculate:(int(^)(int))block; //实现方法(把值传递出去) - (void)calculate:(int (^)(int))block { _result = block(_result); } //在另一个类中定义 CalculateManager *mgr = [[CalculateManager alloc] init]; [mgr calculate:^(int result){ // 计算 result += 5; result *= 2; return result; }];
6.7 block做为方法的返回值
//声明方法 - (CalculateManager *(^)(int))add; //实现方法(此方法可以实现链式点语法) - (CalculateManager *(^)(int))add { return ^(int value){ _result += value; return self; }; } CalculateManager *mgr = [[CalculateManager alloc] init]; mgr.add(5).add(5).add(5).add(5);
6.8 block内存管理:
非ARC环境:block怎么去管理内存
block没有访问外部局部变量,存放到全局区
block访问外部局部变量,block存放栈里面
只要block访问变量,是整个app都在的变量,那么肯定在全局区
在非ARC中.不能使用retain引用block,不会把放在堆里面,在非ARC中只能使用copy,才会把block放在堆里面
ARC环境:
block访问外部局部变量,block存放堆里面
可以使用strong去引用
补充:内存五大区:堆,栈,方法区,全局区,常量区
堆:手动管理内存
栈:不需要手动管理内容,代码块一过,会自动清空栈里面内存
如何判断非ARC环境:
1.重写dealloc,调用super,ARC中不能调用[super dealloc]
2.判断下是否可以调用retain,release等等
非ARC开发中注意:
1.访问属性,不要直接使用_,而是通过set,get方法去访问
2.非ARC中没有weak -> assign,strong -> retain
7 通过写数据到沙盒保存数据,再取数据(NSUserDefaults)
8 单例