iOS传值方式总结

作者: 未来可期me | 来源:发表于2016-11-01 16:21 被阅读469次

时间一长,尤其是在迭代或者维护一个框架成熟的应用的时候,很多基础的东西就会忘记。今天写了个带有block的方法,竟然用了老长时间。看来要总结一下,忘记的时候有个地方,可以翻一翻,看一看。

传值方式都有啥

  • 属性传值
  • 委托Delegate传值
  • 通知NSNotification传值
  • block传值
  • 单例传值
  • runtime动态绑定传值

-----------------------看涨图,放松下-----------------------


one.jpg

说到人生,不管谁都是业余新手啊。 任何人都是第一次参加,人生这种事没有什么专业老手。 by 伊坂幸太郎

1.属性传值

ViewController1页面跳转到ViewController2页面【包括push,或者模态跳转】

  • ViewController2的属性
#import <UIKit/UIKit.h>

@interface ViewController2 : UIViewController

@property (nonatomic, strong)NSString *titleStr;

@end
  • 如何传值,在ViewController1跳转的地方,以下代码
 ViewController2 *viewVc2 = [[ViewController2 alloc] init];
    viewVc2.titleStr = @"传给界面2的值";
    [self presentViewController:viewVc2 animated:YES completion:^{
        
    }];

2.委托Delegate传值

这种方法的使用情景不同于上面的正向传值,相反,当ViewController2消失的时候,它需要传值给ViewController1

写代理的步骤

  • 声明ViewController2的协议--protocol,以及协议方法
  • 在ViewController2的.h文件中声明ViewController2的代理
  • 在ViewController2要进行传值的地方,进行容错处理,即判断他的代理是否实现了自己的协议方法,若完成,就执行,进行传值。
    *在ViewController2的代理--ViewController1中,首先遵守ViewController2的协议,其次,实现ViewController2的协议方法
  • 上面的都完成了,就可以进行传值。
timg.jpg

注意不按这个套路出牌的,往往要吃很多亏。
慢慢长大了,却越来越觉得,这个世界到处都他妈的套路。
到底是我不懂这个世界,还是世界抛弃了我!!!!
我要回村里

下面的例子-----在ViewController2关闭的时候,改变ViewController1的背景颜色
  • 声明ViewController2的协议--protocol,以及协议方法,并且声明代理
#import <UIKit/UIKit.h>

@protocol ViewController2Delegate <NSObject>

- (void)setViewController1BackColor:(UIColor *)color;

@end

@interface ViewController2 : UIViewController

@property (nonatomic, assign)id <ViewController2Delegate>delegate1;

@end

  • 在ViewController2要进行传值的地方,进行容错处理,即判断他的代理是否实现了自己的协议方法,若完成,就执行,进行传值。
#import "ViewController2.h"

@interface ViewController2 ()

@end

@implementation ViewController2

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    
    UIButton *close = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
    close.backgroundColor = [UIColor purpleColor];
    [self.view addSubview:close];
    
    [close addTarget:self action:@selector(closeClick) forControlEvents:UIControlEventTouchUpInside];
    // Do any additional setup after loading the view.
    
}

- (void)closeClick {
    if ([self.delegate1 respondsToSelector:@selector(setViewController1BackColor:)]) {
        [self.delegate1 setViewController1BackColor:[UIColor redColor]];
    }
    
    [self dismissViewControllerAnimated:YES completion:^{
        
    }];

}

  • 在ViewController2的代理--ViewController1中,首先遵守ViewController2的协议,其次,实现ViewController2的协议方法
#import "ViewController.h"
#import "ViewController2.h"

@interface ViewController ()<ViewController2Delegate>

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
     UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
    btn.backgroundColor = [UIColor yellowColor];
    [self.view addSubview:btn];
    
    [btn addTarget:self action:@selector(test) forControlEvents:UIControlEventTouchUpInside];
    
}

- (void)test {
    [self push];
}


- (void)push {
    ViewController2 *viewVc2 = [[ViewController2 alloc] init];
    viewVc2.titleStr = @"传给界面2的值";
    viewVc2.delegate1 = self;
    [self presentViewController:viewVc2 animated:YES completion:^{
        
    }];
}

- (void)setViewController1BackColor:(UIColor *)color {
    self.view.backgroundColor = color;
}

@end

效果图如下

delegate.gif

???????????????????????????????
???????????????????????????????

@property (nonatomic, assign)id <ViewController2Delegate>delegate1;

这儿为什么用assign?????拜读一下下面文章,我也是这意思,哈哈
[点这儿] http://www.jianshu.com/p/398472616435

3.通知NSNotification传值

在ViewController1中,注册观察者,并在dealloc中,移除

#import "ViewController.h"
#import "ViewController2.h"

@interface ViewController ()


@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(notificationClick:) name:@"setViewController1BackColor" object:nil];
    
    UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
    btn.backgroundColor = [UIColor yellowColor];
    [self.view addSubview:btn];
    
    [btn addTarget:self action:@selector(test) forControlEvents:UIControlEventTouchUpInside];
    
}

- (void)notificationClick:(NSNotification *)noti {
    NSDictionary *dic = noti.userInfo;
    self.view.backgroundColor = (UIColor *)dic[@"color"];
}

- (void)test {
    [self push];
}


- (void)push {
    ViewController2 *viewVc2 = [[ViewController2 alloc] init];
    viewVc2.titleStr = @"传给界面2的值";
    [self presentViewController:viewVc2 animated:YES completion:^{
        
    }];
}

- (void)setViewController1BackColor:(UIColor *)color {
    self.view.backgroundColor = color;
}

-(void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self name:nil object:self];
}

@end

在ViewController2中,点击close按钮,发送通知

#import "ViewController2.h"

@interface ViewController2 ()

@end

@implementation ViewController2

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    
    UIButton *close = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
    close.backgroundColor = [UIColor purpleColor];
    [self.view addSubview:close];
    
    [close addTarget:self action:@selector(closeClick) forControlEvents:UIControlEventTouchUpInside];
    // Do any additional setup after loading the view.
    
}

- (void)closeClick {
    [[NSNotificationCenter defaultCenter] postNotificationName:@"setViewController1BackColor" object:self userInfo:@{@"color":[UIColor redColor]}];
    [self dismissViewControllerAnimated:YES completion:^{
        
    }];
}

- (void)viewWillDisappear:(BOOL)animated {
   
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

效果图---与上边一样

4.block传值

block传值是通过block块进行

在ViewController2中定义block属性

//  ViewController2.h
//  JRMBubbleTutorial
//
//  Created by 周钦凯 on 16/11/1.
//  Copyright © 2016年 Caroline Harrison. All rights reserved.
//

#import <UIKit/UIKit.h>

typedef void(^setViewController) (UIColor *color);
@interface ViewController2 : UIViewController

@property (nonatomic, strong)NSString *titleStr;
@property (nonatomic, copy)setViewController block;

@end

在ViewController2.m中利用block声明部分传值

#import "ViewController2.h"

@interface ViewController2 ()

@end

@implementation ViewController2

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    
    UIButton *close = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
    close.backgroundColor = [UIColor purpleColor];
    [self.view addSubview:close];
    
    [close addTarget:self action:@selector(closeClick) forControlEvents:UIControlEventTouchUpInside];
    // Do any additional setup after loading the view.
    
}

- (void)closeClick {
    _block([UIColor redColor]);
    [self dismissViewControllerAnimated:YES completion:^{
        
    }];
}

在ViewController中,初始化ViewController2对象部分,实现属性block的实现部分,在代码块中实现改变ViewController1背景颜色的效果

#import "ViewController.h"
#import "ViewController2.h"



@interface ViewController ()


@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    UIButton *btn = [[UIButton alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
    btn.backgroundColor = [UIColor yellowColor];
    [self.view addSubview:btn];
    
    [btn addTarget:self action:@selector(test) forControlEvents:UIControlEventTouchUpInside];
    
}



- (void)test {
    [self push];
}


- (void)push {
    ViewController2 *viewVc2 = [[ViewController2 alloc] init];
    viewVc2.titleStr = @"传给界面2的值";
    viewVc2.block = ^(UIColor *color) {
        self.view.backgroundColor = [UIColor redColor];
    };
    
    [self presentViewController:viewVc2 animated:YES completion:^{
        
    }];
}

- (void)setViewController1BackColor:(UIColor *)color {
    self.view.backgroundColor = color;
}

效果图依然如上

问题,block为什么用copy修饰
block本身是像对象一样可以retain,和release。但是,block在创建的时候,它的内存是分配在栈(stack)上,而不是在堆(heap)上。他本身的作于域是属于创建时候的作用域,一旦在创建时候的作用域外面调用block将导致程序崩溃。   使用retain也可以,但是block的retain行为默认是用copy的行为实现的,因为block变量默认是声明为栈变量的,为了能够在block的声明域外使用,所以要把block拷贝(copy)到堆,所以说为了block属性声明和实际的操作一致,最好声明为copy。
[详情](http://www.cnblogs.com/MasterPeng/p/5311911.html

learn.jpg

目过代码过千行,撸码如有神 -- °腐

5.单例传值

什么是单例??
单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
1、书写步骤
1)、创建类方法,返回对象实例.以shared default current开头。2)、创建一个全局变量用来保存对象的引用3)、判断对象是否存在,若不存在,创建对象
[点击] http://www.jianshu.com/p/2bdec6f7ebe7

上面单例,为我们在全工程,提供了一个公共的对象,随时随地可以取到,可以算为一种传值方式。如果觉得不是,那看下面这个系统单例。

  • 存数据--- 全局
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    [userDefaults setObject:@"1" forKey:@"isAl"];
    [userDefaults synchronize];

  • 取数据--全局
[userDefaults objectForKey:@"isAl"];

5.runtime传值

有时候,在同一个类里,方法之间传值,我们可以采用runtime动态绑定的方法

动态绑定

// 第一个参数:给哪个对象添加关联 
// 第二个参数:关联的key,通过这个key获取 
// 第三个参数:关联的value 
// 第四个参数:关联的策略 
objc_setAssociatedObject(self, key, name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

动态取值

objc_getAssociatedObject(self, key);

差不多了!!!

相关文章

  • iOS 常用传值方式

    总结 iOS 日常开发中的几种常用传值方式:正向传值代理传值block传值通知传值单例 文章代码:https://...

  • MY_iOS知识点总结

    iOS常用设计模式总结 iOS传值方式总结 有时候,在同一个类里,方法之间传值,我们可以采用runtime动态绑定...

  • iOS传值方式总结

    时间一长,尤其是在迭代或者维护一个框架成熟的应用的时候,很多基础的东西就会忘记。今天写了个带有block的方法,竟...

  • 几种iOS界面之间的传值方式

    几种iOS界面之间的传值方式 一.正向传值方式 (BOOL)application:(UIApplication ...

  • iOS之传值

    在iOS中传值的方式有很多种方式,有最普遍的就是属性传值,代理传值,block传值等方式了。写了OC和swift的...

  • iOS传值方式

    在iOS中,常见的传值方式有以下几种:1.属性传值2.单例传值3.通知传值4.代理传值5.Block这些传值方式,...

  • ios开发逆向传值的几种方法整理

    iOS的逆向传值有很多种方法,下面来总结几种常用的传值方式(只贴相关代码): 第一种:代理传值 第二个控制器: 第...

  • iOS 传值方法(属性传值、代理传值、Block、通知、单例)

    iOS 传值方法(属性传值、代理传值、Block、通知、单例)简单的介绍一下几个传值方式 1、属性传值 在传值的时...

  • ios-传值方式总结

    前段时间学习了OC的页面之间传值的一些方式,感觉比较重要,在此总结一下:传值的几种方式: 1.属性传值 2.通知传...

  • iOS传值的五种方式

    iOS传值的五种方式:分别为属性 代理 block 单例 通知 属性:属性传值是最简单的一种传值方式,此种方式适用...

网友评论

本文标题:iOS传值方式总结

本文链接:https://www.haomeiwen.com/subject/pcemuttx.html