时间一长,尤其是在迭代或者维护一个框架成熟的应用的时候,很多基础的东西就会忘记。今天写了个带有block的方法,竟然用了老长时间。看来要总结一下,忘记的时候有个地方,可以翻一翻,看一看。
传值方式都有啥
- 属性传值
- 委托Delegate传值
- 通知NSNotification传值
- block传值
- 单例传值
- runtime动态绑定传值
-----------------------看涨图,放松下-----------------------
说到人生,不管谁都是业余新手啊。 任何人都是第一次参加,人生这种事没有什么专业老手。 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的协议方法 - 上面的都完成了,就可以进行传值。
注意不按这个套路出牌的,往往要吃很多亏。
慢慢长大了,却越来越觉得,这个世界到处都他妈的套路。
到底是我不懂这个世界,还是世界抛弃了我!!!!
我要回村里
下面的例子-----在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
效果图如下
???????????????????????????????
???????????????????????????????
@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)
目过代码过千行,撸码如有神 -- °腐
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);
差不多了!!!