iOS开发基础之传值

iOS开发的界面传值主要有:属性传值、代理传值、代码块传值、单例传值、KVO传值、通知传值。
下面通过代码举例介绍这6种传值方式

属性传值

假设有A和B两个视图控制器,现在需要从A传值到B,那么首先在B.h文件中声明一个text属性,用来从A传值到B。然后去到A,先导入B.h文件,创建一个B的对象,然后给该对象的text属性赋值,再到B中输出text,会发现text值已从A传到了B,这就是属性传值。

//B的头文件
@interface BViewController : UIViewController

@property (nonatomic,strong)NSString *text;

@end

//A中有一个推送到B的方法,首先得导入B.h
- (void)nextAction {

    BViewController *bvc = [[BViewController alloc] init];
    bvc.text = @"ABC";//推送的时候给text赋值
    [self presentViewController:bvc animated:YES completion:^{

    }];

//在B中输出text
NSLog(@"text=%@",self.text);//输出结果是:text = ABC

单例传值

单例传值的实现思路是:首先创建一个C单例类,然后声明一个要传给A的属性name,同时在C中给name赋值。然后去到A中,先导入C.h头文件,创建一个C对象,然后输出C对象的name属性。

//C的头文件
@interface CViewController : UIViewController

@property (nonatomic,strong)NSString *name;

+ (CViewController *)shareInstance;

@end

//C.m文件中,实现创建单例类的一些操作
//声明一个静态全局cvc对象,并且赋值nil
static CViewController *cvc = nil;
@interface CViewController ()<NSCopying>//需要遵循NSCopying协议

@end

@implementation CViewController

+ (CViewController *)shareInstance {
    if (cvc == nil) {
        cvc = [[CViewController alloc] init];
    }
//    return self->cvc;
    return cvc;
}

+ (id)allocWithZone:(struct _NSZone *)zone {
    @synchronized (self) {
        if (cvc == nil) {
            cvc = [super allocWithZone:zone];
        }
    }    
    return cvc;
}

- (id)copyWithZone:(NSZone *)zone {
    return self;
}
//返回A时调用的方法
- (void)nextAction {
    self.name = @"ZCQ";//返回的时候给name赋值
    [self dismissViewControllerAnimated:YES completion:^{

    }];
}


//到A中创建一个C对象并且输出C的属性
- (void)viewWillAppear:(BOOL)animated {
    CViewController *cvc = [[CViewController alloc] init];
    NSLog(@"%@",cvc.name);//结果是:ZCQ
}

代理传值

代理传值的实现思路是:在D中声明一个协议,该协议里包含一些方法,然后声明一个代理属性,在D中需要在判断代理是否存在及是否遵循协议。然后回到A中遵循该协议并且实现协议里声明的方法从而实现传值。

D.h文件
@protocol passValue <NSObject>

- (void)passOnValue:(NSString *)text;//注意这里的参数跟代码块的区别!!!

@end

@interface DViewController : UIViewController

//@property (nonatomic,strong)NSString *textString;

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

@end

//回到A的方法
- (void)nextAction {
    //判断代理是否存在并且是否遵循该协议
    if (self.delegate && [self.delegate conformsToProtocol:@protocol(passValue)]) {
        [self.delegate passOnValue:@"YF"];//如果存在,则调用协议里的方法
    }
    [self dismissViewControllerAnimated:YES completion:^{

    }];
}

//回到A.m文件
- (void)nextAction {//去到D的方法

    DViewController *dvc = [[DViewController alloc] init];
    dvc.delegate = self;//把A作为dvc的代理
    [self presentViewController:dvc animated:YES completion:^{

    }];
}
//实现协议里的方法
- (void)passOnValue:(NSString *)text {
    NSLog(@"Dtext = %@",text);//输出结果是:Dtext = YF
}

代码块传值

代码块传值的实现思路是:在E中定义一个带参数的代码块,并且声明一个该代码块类型的属性。在返回A的方法中调用该代码块,回到A创建E的对象并且调用代码块。

//E.h文件中
typedef void(^PassValue)(NSString *text);//代码块的参数写法与普通方法的参数写法不一样(NSString *)text

@interface EViewController : UIViewController

@property (nonatomic,copy)PassValue passValue;//内存管理:copy

@end
//E.m文件中
- (void)nextAction {
    //返回A的方法,同时给block赋值
    self.passValue(@"ZCQYF");//传值  
    [self dismissViewControllerAnimated:YES completion:^{

    }];
}

//A.m文件中
//首先需要声明一个全局E类型的属性并且在viewDidLoad中初始化
_evc = [[EViewController alloc] init];

//在viewWillAppear中
- (void)viewWillAppear:(BOOL)animated {
- 
    _evc.passValue = ^(NSString *text){
        NSLog(@"Etext = %@",text);//输出结果:ZCQYF
    };
}

//去到E的方法
- (void)nextAction {

    [self presentViewController:_evc animated:YES completion:^{

    }];
}

KVO传值

创建一个F,在A中观察E中的name属性(注册观察者、定义KVO方法回调、移除观察者),去到F中,在回到A的方法改变属性的值,可以看到A中输出打印变化后的值,这就是KVO传值。

//F.h文件中声明一个要被观察的属性
@interface FViewController : UIViewController
@property (nonatomic,strong)NSString *name;
@end
//F.m文件中,在返回A的方法中改变name的值
- (void)nextAction {
    [self setValue:@"ZCQ" forKey:@"_name"];//设置name的值为"ZCQ"
    [self dismissViewControllerAnimated:YES completion:^{

    }];
}

//回到A.m文件中,viewDidLoad方法中,
    _fvc = [[FViewController alloc] init];//已经声明过的_fvc属性
    //在viewDidLoad注册观察者
    [_fvc addObserver:self forKeyPath:@"_name" options:NSKeyValueObservingOptionNew context:nil];

//定义观察者的方法回调
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {

    NSLog(@"%@",[change objectForKey:NSKeyValueChangeNewKey]);  //输出结果是:ZCQ
}

- (void)dealloc {
    NSLog(@"移除观察者");
    [_fvc removeObserver:self forKeyPath:@"_name"];
}

通知传值

通知传值实现思路:把要传的值放在userInfo中,通过通知中心这个单例发送通知、添加观察者、移除观察者。

//G.m文件返回A的方法
- (void)nextAction {

    [[NSNotificationCenter defaultCenter] postNotificationName:@"通知" object:self userInfo:@{@"name":@"YF"}];//通知中心发送中心

    [self dismissViewControllerAnimated:YES completion:^{

    }];
}
//A.m的viewDidLoad
//通知中心注册观察者
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(shows:) name:@"通知" object:nil];
//方法回调
- (void)shows:(NSNotification *)notification {

    NSLog(@"%@",notification.userInfo[@"name"]);//输出结果是:YF

}
//不要忘了移除观察者,同样也是在通知中心完成
- (void)dealloc {
    NSLog(@"移除观察者");
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值