视图控制器ViewControllers之间的数据传递

这里我们用一个demo来说明ios是如何在视图控制器之间传递重要的参数的。本文先从手写UI来讨论,在下一篇文章中讨论在storyboard中传递数据。

首先新建一个空工程,并添加一个根视图控制器类,如下图所示:

\#

在函数didFinishLunchingWithOption中添加几行代码,完成后如下:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
     self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
     // Override point for customization after application launch.
     self.window.backgroundColor = [UIColor whiteColor];
     [self.window makeKeyAndVisible];
     
     RootViewController *myRootViewController = [[RootViewController alloc] init];
     myRootViewController.view.backgroundColor = [UIColor lightGrayColor];
     self.window.rootViewController = myRootViewController;
     return YES;
}

完成以后运行,iOS模拟器显示结果如下:

 

\#

由图中可以看出,我们自定义的myRootViewController已经成功在启动时加载,显示出了一个浅灰色的界面。

随后如法炮制新建另一个viewController命名为FirstSubViewController,同时在RootViewController的viewDidLoad函数中添加如下代码:

 

?
1
2
3
4
5
6
7
8
9
10
- ( void )viewDidLoad
{
     [ super viewDidLoad];
     // Do any additional setup after loading the view.
     UIButton *firstVC = [UIButton buttonWithType:UIButtonTypeSystem];
     firstVC.frame = CGRectMake( 60 , 244 , 200 , 80 );
     [firstVC setTitle:@ "显示下一个视图" forState:UIControlStateNormal];
     [firstVC addTarget:self action: @selector (displayNextViewController) forControlEvents:UIControlEventTouchUpInside];
     [self.view addSubview:firstVC];
}
之后还需定义一个函数,名为displayNextViewController,函数体暂时设为空。此时运行程序,界面中央将显示一个按钮“显示下一个视图”,但是单击该按钮没有任何反应。这是因为响应函数displayNextViewController还没有实现。现在在该函数中添加代码:

 

 

?
1
2
3
4
5
6
7
- ( void )displayNextViewController
{
     FirstSubViewController *firstSubVC = [[FirstSubViewController alloc] init];
     [self presentViewController:firstSubVC animated:YES completion:^{
         NSLog(@ "present first sub VC ok" );
     }];
}

完成后运行程序发现,按钮已经有反应了,按下后回出现一个新的白色背景的新界面,这就是我们在这里定义的firstSubVC;

 

 

下一步实现界面的返回操作。在FirstSubViewController的viewDidLoad函数中建立一个回退按钮,并实现其响应函数。代码如下:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- ( void )viewDidLoad
{
     [ super viewDidLoad];
     // Do any additional setup after loading the view.
     
     UIButton *goBack = [UIButton buttonWithType:UIButtonTypeSystem];
     goBack.frame = CGRectMake( 60 , 244 , 200 , 80 );
     [goBack setTitle:@ "返回上级界面" forState:UIControlStateNormal];
     [goBack addTarget:self action: @selector (goBackToPreviousViewController) forControlEvents:UIControlEventTouchUpInside];
     [self.view addSubview:goBack];
}
 
- ( void )goBackToPreviousViewController
{
     [self dismissViewControllerAnimated:YES completion:^{
         NSLog(@ "Back to previous OK" );
     }];
}

到此为止,我们已经通过presentViewController和dismissViewController实现了视图的切换,下面来考虑两个视图控制器之间的数据交流的问题。

 

在此之前,分别在RootViewController和FirstSubViewController中添加一个标签和文本框,作为数据的显示和输入部分。我们的目的是在FirstSubViewController中输入一个数字,然后再RootViewController显示出来。

在这两个类中分别用property来实现文本框和标签栏:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//RootViewController.m
@interface RootViewController ()
 
@property (strong,nonatomic) UILabel *lable;
 
@end
 
@implementation RootViewController
 
- (UILabel *)lable
{
     if (!_lable)
     {
         _lable= [[UILabel alloc] initWithFrame:CGRectMake( 60 , 150 , 200 , 30 )];
         _lable.textAlignment = NSTextAlignmentCenter;
         _lable.text = @ "Hello World!" ;
         _lable.backgroundColor = [UIColor whiteColor];
     }
     return _lable;
}
…..
@end
 
//FirstSubViewController
@interface FirstSubViewController ()
 
@property (strong,nonatomic) UITextField *inputText;
 
@end
 
@implementation FirstSubViewController
 
- (UITextField *)inputText
{
     if (!_inputText)
     {
         _inputText = [[UITextField alloc] initWithFrame:CGRectMake( 60 , 150 , 200 , 30 )];
         _inputText.backgroundColor = [UIColor lightGrayColor];
     }
     return _inputText;
}
…..
@end


 

在这两个视图控制器的viewDidLoad中分别添加如下代码:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//RootViewController.m
- ( void )viewDidLoad
{
     [ super viewDidLoad];
     // Do any additional setup after loading the view.
     [self.view addSubview:self.label];
     
     UIButton *firstVC = [UIButton buttonWithType:UIButtonTypeSystem];
     …..
}
…..
//FirstSubViewController
- ( void )viewDidLoad
{
     [ super viewDidLoad];
     // Do any additional setup after loading the view.
     
     //添加输入框
     [self.view addSubview:self.inputText];
     UIButton *goBack = [UIButton buttonWithType:UIButtonTypeSystem];
     …..
}

 

在视图控制器之间进行数据传递可以通过多种方法,下面将逐个实验:

1、使用代理delegate的方法:

基本原理:FirstSubViewControllers试图改变RootViewController的数据,但是除了操作自己内部的数据的能力之外,不能改变其他类的数据。想要将这些数据传递出去,需要设置代理方法,获取FirstSubViewControllers中数据的类来遵循该方法,通过实现该代理协议中的方法来获取FirstSubViewControllers中的数据。

具体步骤:

首先在FirstSubViewController.h中定义协议:

 

?
1
2
3
4
5
6
@protocol FirstSubViewControllerDelegate <nsobject>
 
@optional
- ( void )getStringFromFirstSubViewControllerDelegate:(NSString *)outputString;
 
@end </nsobject>

然后添加一个符合该协议的代理属性:

 

 

?
1
2
@property (nonatomic,weak) id<firstsubviewcontrollerdelegate> delegate;
</firstsubviewcontrollerdelegate>

在RootViewControlller.h中,声明该类符合FirstSubViewControllerDelegate协议:

 

 

?
1
@interface RootViewController : UIViewController<firstsubviewcontrollerdelegate></firstsubviewcontrollerdelegate>

在新建FirstSubViewController的实例后,将其delegate属性定义为self,同时实现协议中的方法,两个函数如下:

 

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
- ( void )getStringFromFirstSubViewControllerDelegate:(NSString *)outputString
{
     self.lable.text = outputString;
}
 
- ( void )displayNextViewController
{
     FirstSubViewController *firstSubVC = [[FirstSubViewController alloc] init];
     firstSubVC.delegate = self;
     [self presentViewController:firstSubVC animated:YES completion:^{
         NSLog(@ "present first sub VC ok" );
     }];
}

最后在FirstSubViewController.m的goBackToPreviousViewController中添加一句向delegate属性发送获取数据的消息:

 

 

?
1
2
3
4
5
6
7
- ( void )goBackToPreviousViewController
{
     [self.delegate getStringFromFirstSubViewControllerDelegate:self.inputText.text];
     [self dismissViewControllerAnimated:YES completion:^{
         NSLog(@ "Back to previous OK" );
     }];
}

 

这样,大功告成了,在FirstSubViewController中的输入框中输入的内容,在按返回按钮后回显示在第一个界面的标签上。

 

2、使用通知Notification的方法

关于通知的知识在未来将会详述,在这里只是简要介绍一种使用通知这一机制的方法。

在使用通知之前,必须在默认通知中心里添加一个所谓“观察者”和通知,这个通知是命名的,同时还指定了回调的方法。当该通知中心收到了某个对象发送了相应的通知时,将会调用指定的方法执行某项操作。通知的发送者同时还可以发送相应的消息作为通知的参数。

注册通知中心可以在RootViewController.m中的viewDidLoad函数的末尾添加如下函数:

 

?
1
2
//使用通知的方式实现
[[NSNotificationCenter defaultCenter] addObserver:self selector: @selector (changeLabelText:) name:@ "ChangeLabelTextNotification" object:Nil];
此外还要实现观察者的回调函数:

 

 

?
1
2
3
4
5
- ( void )changeLabelText:(NSNotification *)notification
{
     id text = notification.object;
     _lable.text = text;
}
自此通知的接收端已经完成。

 

通知的发送端,只需在“返回上级界面”的相应函数中按照事先定义的名称发送通知和参数即可:

 

?
1
2
//使用通知方式实现
[[NSNotificationCenter defaultCenter] postNotificationName:@ "ChangeLabelTextNotification" object:_inputText.text];
此时运行,将会发现和代理模式起到了相同的作用。

 

除了代理和通知之外,还有其他如KVO等方法,未来还会详细探讨。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Laravel 中,创建模型可以使用 Artisan 命令 `make:model`。该命令将在 `app` 目录下创建一个新的模型文件,例如: ``` php artisan make:model User ``` 这将在 `app` 目录下创建一个名为 `User` 的模型文件。 要在 Laravel 中编写相应的路由、控制器视图,可以按照以下步骤进行: 1. 创建路由 在 `routes/web.php` 文件中,可以使用 `Route` 类来定义路由。例如,要创建一个显示所有用户的路由,可以这样写: ``` Route::get('/users', 'UserController@index'); ``` 这将创建一个 `GET` 请求路由,访问 `/users` 路径时将调用 `UserController` 控制器的 `index` 方法。 2. 创建控制器 使用 Artisan 命令 `make:controller` 来创建控制器。例如,要创建一个名为 `UserController` 的控制器,可以这样写: ``` php artisan make:controller UserController ``` 这将在 `app/Http/Controllers` 目录下创建一个名为 `UserController` 的控制器文件。 在 `UserController` 控制器中,可以定义 `index` 方法来显示所有用户: ``` public function index() { $users = User::all(); return view('users.index', ['users' => $users]); } ``` 该方法使用模型查询所有用户,并将它们传递到名为 `users/index.blade.php` 的视图中。 3. 创建视图 使用 Blade 模板引擎来创建视图。例如,要创建名为 `index.blade.php` 的视图文件,可以在 `resources/views/users` 目录下创建一个名为 `index.blade.php` 的文件。 在 `index.blade.php` 文件中,可以使用循环语句来遍历所有用户并显示它们: ``` @foreach ($users as $user) <div>{{ $user->name }}</div> @endforeach ``` 这将遍历所有用户,并在页面上显示它们的名字。 最后,访问 `/users` 路径时,将显示所有用户的名字。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值