1、属性传值 前向后传值。
2、协议传值
3、Block传值 代替协议代理传值,主要时间点问题。
4、单利传值 数据共享。
5、通知传值
正向传值(block)
好像是不能正向传值 (有大佬看到这个 如果能传 麻烦留言一波)
反向传值
定义block有两种方式
格式就是 返回值(^)(参数类型)
typedef void(^wxkBlock)(NSString * valueStr); // wxkBlock不是变量名,而是这种类型的block的别名
@property (nonatomic, copy) wxkBlock wBlcok;
//也可以这样定义 //这样在类中可以拿到self.xkBlock
@property (nonatomic, copy) void(^xkBlock)(NSString * valueStr);
B定义一个block,B ——>A ,对这个block进行操作
- (void) touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
// 如果在上一个页面调用了这个block,就执行下面的方法
if (self.wBlcok) {
self.wBlcok(@"10086"); //把这里的值当参数传递过去
}
[self dismissViewControllerAnimated:YES completion:nil];
}
A进行的操作
// 从ViewController的.m 跳进 ViewControllerB 的点击事件
- (IBAction)exchangeValue:(id)sender{
ViewControllerB * viewB = [[ViewControllerB alloc] init];
/**
wBlcok 是 viewB 的 block
valueStr 为 viewB 传递过来的参数
{}括号里的代码是在viewB的.m文件里传了参数运行block的时候才会调用
*/
viewB.wBlcok = ^(NSString *valueStr) {
NSLog(@"传过来的值 = %@",valueStr);
};
[self presentViewController:viewB animated:YES completion:nil];
}
注
__block关键字的使用
在Block的{}体内,是不可以对外面的变量进行更改的,如果更改会出现如下错误:Variable is not assigning (missing __block type)
NSString *mytitle = @"moxue";
void (^newBlock)(NSString *str) = ^(NSString *str){
mytitle = str;
};
这是因为在初始化block以后,它会默认将和它一起初始化的变量认为是常量,如果要修改外部变量值,只需要在mytitle之前加上一个__block便不会报错
__block NSString *mytitle = @"moxue";
void (^newBlock)(NSString *str) = ^(NSString *str){
mytitle = str;
};
通知传值 (正向 反向)
思考:A->B 怎么直接通知 (直接页面跳转不行 需要改一点小东西)
add post 执行(三部曲)
这是A跳转到B
TwoViewController *vc = [[TwoViewController alloc]init];
[[NSNotificationCenter defaultCenter] postNotificationName:@"changeBgColor" object:nil userInfo:nil];
[self presentViewController:vc animated:YES completion:nil];
B (重写init方法,A->B 先post 再add是监听不到的,将B重写init方法 这样A在创建B的时候就已经add了 再post就能监听了)
- (instancetype)init
{
self = [super init];
if (self) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(changeBgColor:) name:@"changeBgColor" object:nil];
}
return self;
}
B——>A(通知)
这就很简单了,正常逻辑就可以
1.A——>B的时候先add 跳转到B (A已经add了)
2.B——>A在B中post 退回到A 自然能监听到
注:现在不用主动移除通知了
单例传值
单例是oc中设计模式的一种,它的大体概念是:设置一个全局的、不可销毁的静态对象,通过在内部方法中将其赋值,然后在外部通过读取这个静态对象的值来获得所需要的值的传值方式。
https://www.cnblogs.com/scut-linmaojiang/p/5299207.html
实现单例模式有三个条件
1.设计一个私有的构造方法
2.设计一个私有的,本类的对象
3.设计一个类方法,作为2中类对象的全局访问点
接下来我们逐个解决上述3个条件。
首先,将构造函数设计为私有的。在OC中,对象的创建包括两个步骤:内存申请(alloc)和初始化(init)。也就是说,如果我们希望构造函数私有,那么我们要自己定义alloc方法,使得每次调用该方法,都返回条件2中的对象。在OC中,调用alloc时,alloc实际上是调用allocWithZone这个方法来申请内存的,因此,我们在设计单例的时候,要重写这个方法。另外,我们还要保证使用copy复制单例中的对象时,返回的也是步骤2中的对象,而不会重新创建,因此,我们还要重写copyWithZone这个方法。具体代码如下
创建SingleTon
.h
#import <Foundation/Foundation.h>
@interface SingleTon : NSObject
//传值的具体属性
@property (nonatomic,retain)NSString *passValue;
//一般单例是类方法来创建 以default,share,standard,getinstance开头
+(SingleTon*)sharedSingleTon;
@end
SingleTon.m
.m
#import "SingleTon.h"
@implementation SingleTon
+(SingleTon *)sharedSingleTon {
//static 只赋值一次
static SingleTon *singleTon = nil;
//线程锁,保证同时只有一个线程访问
@synchronized(self) {
if (!singleTon) {
singleTon = [[SingleTon alloc]init];
}
}
return singleTon;
}
@end
现在基本都用gcd来实现单例 原因还未探究 有大佬看见 希望直接指出
对于变量前面加static 如果变量在函数内部定义,如 int function(){static int a}表明变量a是一个静态变量(局部的),如果变量在函数外面定义,如 static int a ; int function(){...},表明变量是全局的,在其他文件中无法使用extern 进行引用。
//GCD方法创建单例
static XMPPTools *xmppTools = nil;
+(XMPPTools *)sharedXMPPTool {
//GCD方式创建单例
static dispatch_once_t onceToker;
_dispatch_once(&onceToker, ^{
xmppTools = [[XMPPTools alloc]init];
});
return xmppTools;
}
//重写alloc方法
+ (instancetype)alloc {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
xmppTools = [super alloc];
});
return _xmppTools;
}