iOS编程——OC viewController 传值常用方法Delegate和Block的使用
2015-08-24 13:05
639 查看
写了个例子,简单介绍了下Delegate和Block的使用,注意点都在注释里,直接上代码了:
1.FirstViewController.h:
FirstViewController.m:
2.SecondViewController.h:
SecondViewController.m:
3.测试:
1.FirstViewController.h:
#import <UIKit/UIKit.h> @interface FirstViewController : UIViewController @end
FirstViewController.m:
#import "FirstViewController.h" #import "SecondViewController.h" @interface FirstViewController() <SecondViewDelegate> @property (nonatomic, strong) UITextField *textField; @property (nonatomic, strong) UIButton *button; @end @implementation FirstViewController - (void) viewDidLoad { [super viewDidLoad]; self.title = @"First"; self.view.backgroundColor = [UIColor whiteColor]; CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width; //通过Delegate和Block来改变textField的text self.textField = [[UITextField alloc] initWithFrame:CGRectMake((screenWidth - 300) / 2, 100, 300, 40)]; self.textField.borderStyle = UITextBorderStyleRoundedRect; self.textField.text = @"oldValue"; [self.view addSubview:self.textField]; //跳转button self.button = [UIButton buttonWithType:UIButtonTypeRoundedRect]; self.button.frame = CGRectMake((screenWidth - 300) / 2, 200, 300, 40); [self.button setTitle:@"PushSecondViewController" forState:UIControlStateNormal]; [self.button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; [self.button setBackgroundColor:[UIColor greenColor]]; [self.button addTarget:self action:@selector(pushViewController) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:self.button]; } - (void) pushViewController { SecondViewController *secondViewController = [[SecondViewController alloc] init]; //使用delegate secondViewController.delegate = self; //使用__weak(非arc使用__block)来避免循环引用 __weak SecondViewController *weakSecondViewController = secondViewController; //使用block secondViewController.changeBlock = ^(NSString *newValue) { if (newValue) { self.textField.text = newValue; } //直接调用会报循环引用的警告: Capturing 'secondViewController' strongly in this block is likely to lead to a retain cycle // [secondViewController testRetainCyclesInSecondView]; //解决循环引用 [weakSecondViewController testRetainCyclesInSecondView]; }; [self.navigationController pushViewController:secondViewController animated:YES]; //置为nil,当返回时secondViewController会调用dealloc方法 secondViewController = nil; } #pragma mark ==== SecondViewDelegate Method ==== //实现secondViewController协议 - (void) changeFirstViewValue:(NSString *)newValue { if (newValue) { self.textField.text = newValue; } } @end
2.SecondViewController.h:
#import <UIKit/UIKit.h> //使用delegate先要声明一个协议 @protocol SecondViewDelegate <NSObject> - (void) changeFirstViewValue: (NSString *) newValue; @end //声明一个Block typedef void (^ChangeValueBlock) (NSString *); @interface SecondViewController : UIViewController //实现协议的一个delegate,通过它指向FirstViewController @property (nonatomic, weak) id <SecondViewDelegate> delegate; //声明外部的Block @property (atomic, copy) ChangeValueBlock changeBlock; //测试循环引用 - (void) testRetainCyclesInSecondView; @end
SecondViewController.m:
#import "SecondViewController.h" @interface SecondViewController() @property (nonatomic, strong) UIButton *delegateButton; @property (nonatomic, strong) UIButton *blockButton; @end @implementation SecondViewController //没用引用外部变量的block typedef int (^NoExternalVarBlock) (); NoExternalVarBlock func() { return ^{ return 10;}; } //引用外部变量的block typedef int (^ExternalVarBlock) (); ExternalVarBlock func1() { int i = 10; return ^{ return i;}; } - (void) viewDidLoad { [super viewDidLoad]; self.title = @"Second"; self.view.backgroundColor = [UIColor whiteColor]; CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width; //使用Delegate修改textField的text self.delegateButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; self.delegateButton.frame = CGRectMake((screenWidth - 300) / 2, 100, 300, 40); [self.delegateButton setTitle:@"ChangeFistValueWithDelegate" forState:UIControlStateNormal]; [self.delegateButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; [self.delegateButton setBackgroundColor:[UIColor greenColor]]; [self.delegateButton addTarget:self action:@selector(changeValueWithDelegate) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:self.delegateButton]; //使用Block修改textField的text self.blockButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; self.blockButton.frame = CGRectMake((screenWidth - 300) / 2, 200, 300, 40); [self.blockButton setTitle:@"ChangeFistValueWithBlock" forState:UIControlStateNormal]; [self.blockButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; [self.blockButton setBackgroundColor:[UIColor redColor]]; [self.blockButton addTarget:self action:@selector(changeValueWithBlock) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:self.blockButton]; //测试Block的初始化内存位置(arc下) [self test]; } - (void) test { //block使用 __block NSInteger oneNum = 10;//不使用__block报错: Variable is not assignable (missing __block type specifier) NSInteger (^testBlock) (NSInteger) = ^(NSInteger num){ oneNum += num; return num * num; }; NSLog(@"%ld",(long)testBlock(10)); //没有引用外部变量的block,无论arc还是marc都是__NSGlobalBlock__,不需要考虑作用域问题。 NoExternalVarBlock nevBlock = func(); NSLog(@"%@",[nevBlock class]); NSLog(@"%p",nevBlock); NoExternalVarBlock nevBlock1 = [nevBlock copy]; NSLog(@"%p",nevBlock1); //引用了外部变量的block,没有copy的话它的作用域只存在函数栈内,类型为__NSStackBlock__,非arc下会报错,arc下自动进行了copy,不会报错。 ExternalVarBlock evBlock = func1(); NSLog(@"%@",[evBlock class]); NSLog(@"%p",evBlock); } - (void) changeValueWithDelegate { if (self.delegate && [self.delegate respondsToSelector:@selector(changeFirstViewValue:)]) { //如果FirstViewController设置了代理并且实现了协议,就会进来 [self.delegate changeFirstViewValue:@"newValueWithDelegate"]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Alert" message:@"textField did changed with Delegate.\n Back to see the result." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; [alert show]; alert = nil; } } - (void) changeValueWithBlock { //使用atomic保证原子性但是并未实现线程安全,在使用时可以先把block赋值给本地变量,这样防止block被别的线程改变,防止因为空值导致的crash ChangeValueBlock localBlock = self.changeBlock; if (localBlock) { localBlock(@"newValueWithBlock"); UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Alert" message:@"textField did changed with Block. Back to see the result." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil]; [alert show]; alert = nil; } //mrc下需要手动retain下block, // ChangeValueBlock localBlock = [self.changeBlock retain]; // if (localBlock) { // localBlock(@"newValueWithBlock"); // } // [localBlock release]; } - (void) testRetainCyclesInSecondView { NSLog(@"test retain cycles."); } - (void) dealloc { //SecondViewController释放会调用此方法,检查有没有释放。 NSLog(@"SecondViewController dealloc."); } @end
3.测试:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. FirstViewController *firstVC = [[FirstViewController alloc] init]; UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:firstVC]; self.window.rootViewController = navigationController; return YES; }
相关文章推荐
- iOS8 CLLocationManager 的改变导致 locationManager didUpdateLocations不能被调用的解决办法
- iOS 8 Handoff 开发指南
- IOS中判断输入的字符串是否为整形
- 访园助手ios端项目小结
- iOS开发 两个视图之间值传递的常用方法<五>
- CocoaPods的简单使用
- iOS开发-常用第三方开源框架介绍(你了解的ios只是冰山一角)
- iOS开发 两个视图之间值传递的常用方法<四>
- 【iOS知识学习】_iPhone学习提交git@OSC
- iOS容易造成循引用的场景
- iOS 万能跳转界面方法 (runtime实用篇一)
- iOS中block的使用、实现底层、循环引用、存储位置
- ios 取消左滑手势
- ios下最简单的正则,RegexKitLite
- iOS学习笔记18- iOS检查版本更新
- IOS常用宏定义
- IOS 断点下载
- iOS学习笔记17-直接拿来用!最火的iOS开源项目(三)
- iOS学习笔记16-直接拿来用!最火的iOS开源项目(二)
- iOS学习笔记15- 直接拿来用!最火的iOS开源项目(一)