视图间跳转完成数据回调的四种方法

从视图Master跳转到视图Data,在Data视图中准备好数据,然后从Data视图回到Master视图,这个时候要将Data视图准备好的数据回调到Master视图中,此时有三种方法去实现。此时有四种方法去实现。


方法一:使用全局变量

将Master视图控制器设置为全局变量,直接在Data视图控制器中进行存取。

首先在程序委托AppDelegate.h中声明全局变量:

#import <UIKit/UIKit.h>
#import "Global_MasterViewController.h"
#import "Property_MasterViewController.h"
#import "Delegate_MasterViewController.h"

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@property (strong, nonatomic) UITabBarController *tbc;

@property (strong, nonatomic) Global_MasterViewController *g_mVC; // 定义全局变量

@end
然后是Global_MasterViewController类:

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // 标题
    self.navigationItem.title = @"Global";
    
    // Modal按钮,点击后跳转到Data视图
    CGRect rect = CGRectMake(120.0, 230.0, 80.0, 40.0);
    self.modal_button = [UIButton buttonWithType:UIButtonTypeSystem];
    self.modal_button.frame = rect;
    [self.modal_button setTitle:@"Modal" forState:UIControlStateNormal];
    [self.modal_button addTarget:self action:@selector(modalToDataView:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:self.modal_button];
    
    // data标签,用来显示data视图中输入的数据
    rect = CGRectMake(100.0, 300.0, 120.0, 40.0);
    self.data_label = [[UILabel alloc] initWithFrame:rect];
    self.data_label.textAlignment = NSTextAlignmentCenter;
    [self.view addSubview:self.data_label];
}

// 跳转到Data视图
-(void)modalToDataView:(id)sender
{
    Global_DataViewController *g_dVC = [[Global_DataViewController alloc] init];
    g_dVC.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
    [self presentViewController:g_dVC animated:YES completion:nil];
}
该视图有一个modal按钮,点击后跳转到Data视图,Data视图有一个文本输入框。

该视图的data标签用于显示Data视图输入的数据。
接着是Global_DataViewController类:

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // 文本输入框,用于输入数据
    self.tf = [[UITextField alloc] initWithFrame:CGRectMake(100.0, 200.0, 120.0, 100.0)];
    self.tf.placeholder = @"Input some text";
    [self.view addSubview:self.tf];
    
    // Dismiss按钮,dismiss当前视图
    self.dismiss_button = [UIButton buttonWithType:UIButtonTypeSystem];
    self.dismiss_button.frame = CGRectMake(130.0, 320.0, 60.0, 40.0);
    [self.dismiss_button setTitle:@"Dismiss" forState:UIControlStateNormal];
    [self.dismiss_button addTarget:self action:@selector(modalBack:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:self.dismiss_button];
}

// 回到Master视图,并完成数据回调
-(void)modalBack:(id)sender
{
    AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate]; // 通过appDelegate获取全局变量g_mVC
    appDelegate.g_mVC.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
    [self dismissViewControllerAnimated:YES completion:^{
        appDelegate.g_mVC.data_label.text = self.tf.text; // 设置g_mVC中标签显示的数据
    }];
}


方法二:使用数据成员

将Master视图控制器设定为Data视图控制器的成员变量,然后可以在Data视图控制器中进行存取。

首先设定Master视图控制器类为Data视图控制器类的成员变量:

@interface Property_DataViewController : UIViewController

@property (strong, nonatomic) UIButton *dismiss_button;

@property (strong, nonatomic) UITextField *tf;

@property (strong, nonatomic) Property_MasterViewController *p_mVC; // 设定Master视图控制器为Data视图控制器的成员变量

@end
接着是Property_MasterViewController类:

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // 标题
    self.navigationItem.title = @"Property";
    
    // Modal按钮,点击后跳转到Data视图
    CGRect rect = CGRectMake(120.0, 230.0, 80.0, 40.0);
    self.modal_button = [UIButton buttonWithType:UIButtonTypeSystem];
    self.modal_button.frame = rect;
    [self.modal_button setTitle:@"Modal" forState:UIControlStateNormal];
    [self.modal_button addTarget:self action:@selector(modalToDataView:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:self.modal_button];

    // data标签,用来显示data视图中输入的数据
    rect = CGRectMake(100.0, 300.0, 120.0, 40.0);
    self.data_label = [[UILabel alloc] initWithFrame:rect];
    self.data_label.textAlignment = NSTextAlignmentCenter;
    [self.view addSubview:self.data_label];
}

// 跳转到Data视图
-(void)modalToDataView:(id)sender
{
    Property_DataViewController *p_dVC = [[Property_DataViewController alloc] init];
    p_dVC.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
    [self presentViewController:p_dVC animated:YES completion:^{
        p_dVC.p_mVC = self; // 设定Data视图的master成员变量为self
    }];
}
在跳转时必须要设定好Data视图控制器的master成员变量为self。
最后是Property_DataViewController类:
- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // 文本输入框,用于输入数据
    self.tf = [[UITextField alloc] initWithFrame:CGRectMake(100.0, 200.0, 120.0, 100.0)];
    self.tf.placeholder = @"Input some text";
    [self.view addSubview:self.tf];
    
    // Dismiss按钮,dismiss当前视图
    self.dismiss_button = [UIButton buttonWithType:UIButtonTypeSystem];
    self.dismiss_button.frame = CGRectMake(130.0, 320.0, 60.0, 40.0);
    [self.dismiss_button setTitle:@"Dismiss" forState:UIControlStateNormal];
    [self.dismiss_button addTarget:self action:@selector(modalBack:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:self.dismiss_button];
}
                                                                                                                                                          // 跳转到Data视图
-(void)modalBack:(id)sender{
self.p_mVC.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal; 
[self dismissViewControllerAnimated:YES completion:^{ self.p_mVC.data_label.text = self.tf.text; // 设置self.p_mVC中标签显示的数据 }];}


方法三:使用委托
由于Master视图控制器要使用Data视图控制器中的数据,所以可以在Data视图控制器中声明一个委托,然后Master视图控制器通过实现委托中的方法直接从Data视图控制器中获取数据。
先看看Data视图中委托的声明部分:

// 声明数据回调委托
@protocol DataCallBackDelegate <NSObject>
-(void)willDismissModalView:(id)sender;
@end

@interface Delegate_DataViewController : UIViewController

@property (strong, nonatomic) UIButton *dismiss_button;

@property (strong, nonatomic) UITextField *tf;

@property (weak, nonatomic) id<DataCallBackDelegate> dataDelegate; // 声明数据回调委托作为该类的成员变量,必须设定为weak属性,否则会形成retain cycle

@end
然后是Delegate_MasterViewController的接口部分:
@interface Delegate_MasterViewController : UIViewController <DataCallBackDelegate> // confirm to DataCallBackDelegate

@property (strong, nonatomic) UIButton *modal_button;

@property (strong, nonatomic) UILabel  *data_label;

@end
实现部分:
- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // 标题
    self.navigationItem.title = @"Delegate";
    
    // Modal按钮,点击后跳转到Data视图
    CGRect rect = CGRectMake(120.0, 230.0, 80.0, 40.0);
    self.modal_button = [UIButton buttonWithType:UIButtonTypeSystem];
    self.modal_button.frame = rect;
    [self.modal_button setTitle:@"Modal" forState:UIControlStateNormal];
    [self.modal_button addTarget:self action:@selector(modalToDataView:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:self.modal_button];
    
    // data标签,用来显示data视图中输入的数据
    rect = CGRectMake(100.0, 300.0, 120.0, 40.0);
    self.data_label = [[UILabel alloc] initWithFrame:rect];
    self.data_label.textAlignment = NSTextAlignmentCenter;
    [self.view addSubview:self.data_label];
}

// 跳转到Data视图
-(void)modalToDataView:(id)sender
{
    Delegate_DataViewController *d_dVC = [[Delegate_DataViewController alloc] init];
    d_dVC.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
    d_dVC.dataDelegate = self; // 必须设定Data视图控制器的委托为self
    [self presentViewController:d_dVC animated:YES completion:nil];
}

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

#pragma mark -
#pragma mark Data call back delegate

// 实现委托中的方法
-(void)willDismissModalView:(id)sender
{
    Delegate_DataViewController *d_dVC = (Delegate_DataViewController *)sender;
    self.data_label.text = d_dVC.tf.text; // 设置self的标签显示的数据
}
最后看看Delegate_DataViewController类:
- (void)viewDidLoad
{
    [super viewDidLoad];
    
    // 文本输入框,用于输入数据
    self.tf = [[UITextField alloc] initWithFrame:CGRectMake(100.0, 200.0, 120.0, 100.0)];
    self.tf.placeholder = @"Input some text";
    [self.view addSubview:self.tf];
    
    // Dismiss按钮,dismiss当前视图
    self.dismiss_button = [UIButton buttonWithType:UIButtonTypeSystem];
    self.dismiss_button.frame = CGRectMake(130.0, 320.0, 60.0, 40.0);
    [self.dismiss_button setTitle:@"Dismiss" forState:UIControlStateNormal];
    [self.dismiss_button addTarget:self action:@selector(modalBack:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:self.dismiss_button];
}

// 回到Master视图,并完成数据回调
-(void)modalBack:(id)sender
{
    [self dismissViewControllerAnimated:YES completion:^{
        [self.dataDelegate willDismissModalView:self]; // 调用委托中的方法实现数据回调
    }];
}
这个比较特别:将委托的调用和实现分离开来。
在本例中,在Data视图控制器中调用委托方法:
// 回到Master视图,并完成数据回调
-(void)modalBack:(id)sender
{
    [self dismissViewControllerAnimated:YES completion:^{
        [self.dataDelegate willDismissModalView:self]; // 调用委托中的方法实现数据回调
    }];
}
实现则在Master视图控制器中完成:
// 实现委托中的方法
-(void)willDismissModalView:(id)sender
{
    Delegate_DataViewController *d_dVC = (Delegate_DataViewController *)sender;
    self.data_label.text = d_dVC.tf.text; // 设置self的标签显示的数据
}
注意要设置好委托为self。

Demo已上传,可以下载看看。



后记:

方法四:注册通知中心

最近看到一个注册通知中心在页面间传值的方法,现在特地写下来做个笔记。

假设有ViewController和NewViewController两个视图控制器,ViewController中有一个变量data,NewViewController中对data的属性值进行设置,并将设置后的值回调到ViewController中。

原理很简单,首先将ViewController注册到通知中心中作为消息观察者,然后在跳转到NewViewController后,在NewViewController中post一个消息,ViewController在收到相应的消息后调用@selector中的方法对变量data的值作出更改。

先看看故事板:


然后是代码。

首先是ViewController类:

#import "ViewController.h"

@interface ViewController ()

@property (nonatomic, strong) NSString *data;

@end

@implementation ViewController
@synthesize data;
@synthesize showData_label;

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
    // 将自己注册到通知中心中
    [notificationCenter addObserver:self                       // 消息观察者:self
                           selector:@selector(setMyData:)      // 收到消息后的处理方法
                               name:@"SetDataOfViewController" // 消息名
                             object:nil];                      // 发送消息的对象,即Poster
    
    data = nil; // 一开始设置data为空
}

/* 在收到消息后调用该方法 */
- (void)setMyData:(NSNotification *)notification {
    NSString *value = (NSString *)[notification object]; // 获取消息传递的对象
    data = value;
    
    if (data) {
        showData_label.text = data;
    }
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    
    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
    [notificationCenter removeObserver:self];
    
    self.data = nil;
    self.showData_label = nil;
}

@end

接着是NewViewController类:

#import "NewViewController.h"

@interface NewViewController ()

@end

@implementation NewViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
}

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

/* 点击Set按钮后发送的动作 */
- (IBAction)setDataOfViewController:(id)sender {
    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
    [notificationCenter postNotificationName:@"SetDataOfViewController" object:@"ViewController"]; // 向通知中心Post一条名为SetDataViewController的消息,传递的对象为@"View Controller"
    
    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Notification Posted" message:nil delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
    [alertView show];
}

@end

Run看看:



在点击Push按钮后将跳转到NewViewController:


点击Set按钮后,将发送消息并提示成功。


回到ViewController,可以看到:


中间的标签显示我们Post消息时传递的对象:ViewController。


Demo已经补传,可以下载看看。


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在Xcode中,可以使用多种方法实现视图的转换。下面是一些常用的方法及其示例: 1. 使用Segue实现视图的转换 Segue是一种在Storyboard中定义视图转换的方法。在Storyboard中,可以通过Ctrl拖拽一个视图控制器之的连接线来创建一个Segue,然后设置Segue的类型和标识符。在代码中,可以通过performSegue(withIdentifier:sender:)方法来触发Segue的执行。 示例:在一个应用中,有两个视图控制器,一个是登录页面,一个是主页面。在Storyboard中,我们可以创建一个名为“loginToMain”的Segue,然后在登录页面中编写以下代码来触发Segue的执行: ```swift performSegue(withIdentifier: "loginToMain", sender: nil) ``` 2. 使用Present和Dismiss实现模态视图的转换 Present和Dismiss是一种在代码中实现视图转换的方法,适用于模态视图的转换。在代码中,可以使用present(_:animated:completion:)方法将一个视图控制器以模态形式显示在另一个视图控制器上,然后使用dismiss(animated:completion:)方法将其关闭。 示例:在一个应用中,有一个设置页面,用户可以在该页面中修改应用的设置。当用户点击“保存”按钮时,我们希望将设置页面关闭,并返回到主页面。在设置页面中,可以编写以下代码来实现这一功能: ```swift @IBAction func saveButtonTapped(_ sender: UIButton) { // 保存设置 dismiss(animated: true, completion: nil) } ``` 3. 使用Navigation Controller实现多个视图的转换 Navigation Controller是一种用于管理多个视图控制器之转换的容器控制器。在Storyboard中,可以将多个视图控制器嵌套在Navigation Controller中,然后使用push和pop方法在它们之转换。在代码中,可以使用pushViewController(_:animated:)和popViewController(animated:)方法来实现这一功能。 示例:在一个应用中,有一个包含多个列表项的主页面,每个列表项都可以进入一个详细页面进行查看。我们可以使用Navigation Controller来管理这些页面之的转换。在Storyboard中,我们可以将主页面和详细页面嵌套在一个Navigation Controller中,然后在主页面中编写以下代码来实现转换: ```swift func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let detailViewController = storyboard?.instantiateViewController(withIdentifier: "DetailViewController") as! DetailViewController detailViewController.item = items[indexPath.row] navigationController?.pushViewController(detailViewController, animated: true) } ``` 以上是一些在Xcode中实现视图转换的常用方法及其示例。 ### 回答2: 在Xcode中,可以使用不同的方法来实现视图的转换,例如通过导航控制器、模态视图以及自定义动画过渡等方式。 1. 导航控制器:导航控制器是iOS平台中常用的一种视图转换方式。通过导航控制器可以方便地实现多个视图的导航操作,比如从一个视图跳转到另一个视图,以及返回上一级视图。在Xcode中使用导航控制器进行视图的转换可以通过以下步骤完成: 1) 在Xcode中创建一个导航控制器,并将其设置为应用程序的根视图控制器。 2) 创建多个视图控制器,并添加到导航控制器的视图控制器栈中。 3) 在需要进行视图转换的地方,通过调用导航控制器的pushViewController方法将目标视图控制器推入导航控制器的栈中,实现从当前视图到目标视图的转换。 4) 如果需要返回上一级视图,可以通过调用导航控制器的popViewController方法实现返回操作。 例如,在一个应用中有两个视图控制器A和B,我们可以通过创建一个导航控制器,并将A设置为导航控制器的根视图控制器,然后通过点击一个按钮触发相应的事件,调用导航控制器的pushViewController方法将B推入导航控制器的栈中,从而实现从A到B的转换。 2. 模态视图:模态视图是另一种实现视图转换的方法。通过模态视图可以在屏幕顶部以浮动窗口的形式展示一个新的视图,并且在用户交互完成后可以关闭该视图返回到上一级视图。在Xcode中使用模态视图进行视图的转换可以通过以下步骤完成: 1) 在Xcode中创建一个新的视图控制器,用于展示模态视图内容。 2) 在需要触发模态视图展示的地方,通过调用当前视图控制器的present方法,并传入需要展示的目标视图控制器实例以及展示风格等参数,实现从当前视图到目标视图的转换。 3) 在目标视图控制器中,通过调用dismiss方法关闭模态视图,返回到上一级视图。 例如,在一个应用中有一个视图控制器A和一个视图控制器B,我们可以通过在A中点击一个按钮触发相应的事件,调用当前视图控制器的present方法,并将B作为目标视图控制器传入,从而将B以模态视图的形式展示在A之上,用户交互完成后可以调用B的dismiss方法关闭B,返回到A。 3. 自定义动画过渡:如果需要实现一些独特的视图转换效果,可以通过自定义动画过渡来实现。在Xcode中可以使用Core Animation框架来创建和管理视图的自定义过渡动画。通过Core Animation,开发者可以控制视图的位置、大小、旋转、透明度等属性,并通过动画来改变这些属性,从而实现独特的视图转换效果。 例如,我们可以通过创建一个自定义的动画对象,并设置相应的动画属性,然后将这个动画对象应用到需要进行转换的视图上,从而实现自定义的过渡效果,比如渐变、滑动、翻转等等。在动画完成后,可以回调相应的事件来处理视图的切换。 ### 回答3: Xcode是苹果公司提供的一款用于开发iOS和macOS应用程序的集成开发环境。在Xcode中,实现视图的转换通常使用导航控制器、模态视图和页面传参的方式。 一、使用导航控制器进行视图转换 导航控制器是Xcode中常用的视图转换方式之一。通过导航控制器,我们可以实现视图的有序转换,形成一种堆栈式的页面管理体系。下面以实现从首页跳转到详情页为例,步骤如下: 1. 创建导航控制器:在Xcode中创建一个新的导航控制器,并将其作为应用程序的根视图控制器。 2. 创建首页和详情页:在导航控制器中添加首页和详情页两个视图控制器。 3. 添加按钮:在首页视图中添加一个按钮,用于触发跳转到详情页的操作。 4. 设置按钮事件:在按钮的点击事件中,调用导航控制器的push方法,将详情页视图推入导航堆栈中。 5. 在详情页中处理返回操作:在详情页中,可以使用导航控制器的pop方法进行返回操作。 二、使用模态视图进行视图转换 模态视图是另一种常用的视图转换方式,在新视图中展示一部分内容,通常用于显示弹窗、选择器等需要暂时中断当前流程的场景。下面以实现从登录页跳转到注册页为例,步骤如下: 1. 创建登录页和注册页:在Xcode中创建登录页和注册页两个视图控制器。 2. 添加登录按钮:在登录页视图中添加一个登录按钮,用于触发跳转到注册页的操作。 3. 设置按钮事件:在按钮的点击事件中,使用模态视图的方式present出注册页视图。 4. 在注册页中处理关闭操作:在注册页中可以添加一个关闭按钮,通过模态视图的dismiss方法来关闭当前视图。 三、页面传参进行视图转换 有时候需要将数据从一个视图传递到另一个视图,此时可以使用页面传参的方式。下面以实现从列表页跳转到详情页,并传递选中项的数据为例,步骤如下: 1. 创建列表页和详情页:在Xcode中创建列表页和详情页两个视图控制器。 2. 添加列表项:在列表页中显示多个列表项,并为每个列表项添加一个点击事件。 3. 设置点击事件:在列表项的点击事件中,创建一个详情页视图实例,并将选中的数据作为参数传递给详情页。 4. 在详情页中接收参数:在详情页的生命周期方法中,接收从列表页传递过来的参数,并使用这些数据进行页面的展示。 通过以上的方法,我们可以在Xcode中实现视图的转换,并且可以根据不同的场景使用不同的方法。这些方法可以使应用程序的功能更加丰富和易于交互。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值