概要
很多时候,不同的类之间需要有数值交流传递,但是这些类之间并没有直接的关系,比如当一个界面向子页面传递某个参数,而子页面修改某些值之后而再返回主页面的时候,主页面的UI需要根据子页面的状态做一定的UI更新,这时,就需要考虑参数传递的问题了。这里使用IOS的代理的特点,以担当参数传递的职责。
主要技术点
- 本例子的实验效果如下所示
其中主页面输入的用户ID是通过代理(用户信息代理)的方式传递给子页面(用户信息页面)的,因此用户信息界面根据传递的用户ID查找用户头像,并生成一些信息,同时在用户信息里面通过代理(用户信息代理)设置主页面的用户头像,具体效果上图的动画已有演示。 - 用户信息代理协议如下
该协议有两个方法,方法userId是用于传进参数,方法setPortraitPath:用于传出参数,这两个方法都是由使用了该协议(不是实现了该协议)的类调用,调用的大致方法如下:@protocol UserInfoDelegate <NSObject> @required /** * 获取用户Id * * @return 用户ID */ - (NSString*)userId; @optional /** * 默认头像 */ - (void) setPortraitPath:(NSString*)portrait; @end
上述代码中使用方法respondsToSelector是查看是否实现了该方法,需要注意的是,这里调用的两个方法都是在实现了代理协议的类里面实现的,而不是当前类实现。需要注意用户信息类要有属性或者变量类型为id<UserInfoDelegate>的,如下所示:- (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; UILabel* userLabel = [[UILabel alloc] init]; userLabel.frame = CGRectMake(40, 200, 200, 30); // 设置了代理 if ([_delegate respondsToSelector:@selector(userId)]) { userLabel.text = [_delegate userId]; } else { userLabel.text = @"Delegate not set"; } /** 中间代码略 */ // 更新对应代理的头像 if ([_delegate respondsToSelector:@selector(userId)]) { [_delegate setPortraitPath:imagePath]; } }
@interface UserInfo : UIViewController @property (nonatomic, strong) id<UserInfoDelegate> delegate; @end
- 实现代理协议的类是主页面,实现协议就好了
然后在转入子页面的时候,设置子页面的代理为当前实例,如此完成了整个部分的参数传值过程。#pragma 实现协议UserInfoDelegate // 当前视图的值传值给对方 - (NSString*)userId { return _userText.text; } // 对方视图的值传值到本类 - (void) setPortraitPath:(NSString*)portrait { if (portrait == nil) { portrait = [[NSBundle mainBundle] pathForResource:@"boy0" ofType:@"png"]; } // 设置头像 _portraitView.image = [UIImage imageWithData:[NSData dataWithContentsOfFile:portrait]]; }
- (void)goUser { UserInfo* user = [[UserInfo alloc] init]; // 设置代理 user.delegate = self; [self.navigationController pushViewController:user animated:YES]; }
- 这样当主页面输入完用户ID后,转到子页面的viewDidLoad方法,由于该方法所在的类拥有设置了用户信息代理(UserInfoDelegate)方,所以可直接使用协议的方法。于是先是通过调用协议的方法userId拿到当前的用户id值,然后根据id查找获取用户id对应的信息,同时在最后通过代理的setPortraitPath:方法向实现代理的对象返回头像路径值。
主要代码
用户信息视图控制类头文件
// Copyright (c) 2015年 arbboter. All rights reserved.
//
#import <UIKit/UIKit.h>
@protocol UserInfoDelegate <NSObject>
@required
/**
* 获取用户Id
*
* @return 用户ID
*/
- (NSString*)userId;
@optional
/**
* 默认头像
*/
- (void) setPortraitPath:(NSString*)portrait;
@end
@interface UserInfo : UIViewController
@property (nonatomic, strong) id<UserInfoDelegate> delegate;
@end
用户信息视图控制类实现文件
// Copyright (c) 2015年 arbboter. All rights reserved.
//
#import "UserInfo.h"
@implementation UserInfo
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
UILabel* userLabel = [[UILabel alloc] init];
userLabel.frame = CGRectMake(40, 200, 200, 30);
// 设置了代理
if ([_delegate respondsToSelector:@selector(userId)])
{
userLabel.text = [_delegate userId];
}
else
{
userLabel.text = @"Delegate not set";
}
userLabel.layer.borderWidth = 1;
userLabel.textAlignment = NSTextAlignmentCenter;
[self.view addSubview:userLabel];
UILabel* nameLabel = [[UILabel alloc] init];
nameLabel.frame = CGRectMake(40, 240, 200, 30);
nameLabel.layer.borderWidth = 1;
nameLabel.textAlignment = NSTextAlignmentCenter;
nameLabel.text = [NSString stringWithFormat:@"name_%d", arc4random()];
[self.view addSubview:nameLabel];
UILabel* stateLabel = [[UILabel alloc] init];
stateLabel.frame = CGRectMake(40, 280, 200, 30);
stateLabel.layer.borderWidth = 1;
stateLabel.text = @"该家伙太懒了,什么都没有留下。请邀请ta更新....";
// 高度自适应
stateLabel.numberOfLines = 0;
[stateLabel sizeToFit];
[self.view addSubview:stateLabel];
UIImageView* portrait = [[UIImageView alloc] init];
portrait.frame = CGRectMake(100, 80, 100, 100);
portrait.layer.borderWidth = 1;
NSString* imagePath = [[NSBundle mainBundle] pathForResource:userLabel.text ofType:@"png"];
if(imagePath == nil)
{
imagePath = [[NSBundle mainBundle] pathForResource:@"boy3" ofType:@"png"];
userLabel.text = @"user not exist";
}
portrait.image = [UIImage imageWithData:[NSData dataWithContentsOfFile:imagePath]];
portrait.contentMode = UIViewContentModeScaleAspectFit;
[self.view addSubview:portrait];
// 更新对应代理的头像
if ([_delegate respondsToSelector:@selector(userId)])
{
[_delegate setPortraitPath:imagePath];
}
}
@end
主页面视图控制类
// Copyright (c) 2015年 arbboter. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong) UIImageView* portraitView;
@property (nonatomic, strong) UITextField* userText;
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
[super.navigationController setNavigationBarHidden:YES animated:TRUE];
//[super.navigationController setToolbarHidden:YES animated:TRUE];
_portraitView = [[UIImageView alloc] init];
_portraitView.frame = CGRectMake(100, 40, 150, 150);
[self.view addSubview:_portraitView];
UILabel* userLabel = [[UILabel alloc] init];
userLabel.frame = CGRectMake(40, 200, 60, 30);
userLabel.text = @"用户ID";
[self.view addSubview:userLabel];
_userText = [[UITextField alloc] init];
_userText.frame = CGRectMake(100, 200, 200, 30);
_userText.placeholder = @"请输入用户ID";
_userText.returnKeyType = UIReturnKeyGo;
_userText.layer.borderWidth = 1;
[_userText addTarget:self action:@selector(goUser) forControlEvents:UIControlEventEditingDidEndOnExit];
[self.view addSubview:_userText];
_portraitView = [[UIImageView alloc] init];
_portraitView.frame = CGRectMake(100, 80, 100, 100);
_portraitView.contentMode = UIViewContentModeScaleAspectFit;
[self.view addSubview:_portraitView];
[self setPortraitPath:nil];
}
- (void)goUser
{
UserInfo* user = [[UserInfo alloc] init];
// 设置代理
user.delegate = self;
[self.navigationController pushViewController:user animated:YES];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void) viewWillAppear:(BOOL)animated
{
// 隐藏导航栏
[super.navigationController setNavigationBarHidden:YES animated:animated];
}
- (void) viewWillDisappear:(BOOL)animated
{
// 显示导航栏
[super.navigationController setNavigationBarHidden:NO animated:animated];
}
#pragma 实现协议UserInfoDelegate
// 当前视图的值传值给对方
- (NSString*)userId
{
return _userText.text;
}
// 对方视图的值传值到本类
- (void) setPortraitPath:(NSString*)portrait
{
if (portrait == nil)
{
portrait = [[NSBundle mainBundle] pathForResource:@"boy0" ofType:@"png"];
}
// 设置头像
_portraitView.image = [UIImage imageWithData:[NSData dataWithContentsOfFile:portrait]];
}
@end