gpt4 book ai didi

ios - 在 View Controller 之间传递数据

转载 作者:行者123 更新时间:2023-11-29 05:49:45 25 4
gpt4 key购买 nike

我是iOS和Objective-C以及整个MVC范例的新手,我坚持以下几点:

我有一个充当数据输入表单的视图,我想给用户选择多个产品的选项。这些产品在另一个视图上用UITableViewController列出,并且我启用了多个选择。

我的问题是,如何将数据从一个视图传输到另一个视图?我将把选择保留在数组中的UITableView上,但是如何将其传递回先前的数据输入表单视图,以便在提交表单时将其与其他数据一起保存到Core Data?

我到处冲浪,看到有人在应用程序委托中声明了一个数组。我读了一些有关Singletons的内容,但不了解它们是什么,并且读了一些有关创建数据模型的知识。

什么是执行此操作的正确方法,我将如何处理?

最佳答案

这个问题在stackoverflow上似乎很受欢迎,所以我想我会尝试给出一个更好的答案来帮助像我这样的iOS初学者。

我希望这个答案足够清晰,让人们理解,并且我没有错过任何东西。

向前传递数据

将数据从另一个视图控制器传递到视图控制器。如果要将对象/值从一个视图控制器传递到可能要推送到导航堆栈的另一个视图控制器,则可以使用此方法。

对于此示例,我们将具有ViewControllerAViewControllerB

要将BOOL值从ViewControllerA传递到ViewControllerB,我们将执行以下操作。


ViewControllerB.h中为BOOL创建一个属性

@property (nonatomic, assign) BOOL isSomethingEnabled;

ViewControllerA中,您需要介绍一下 ViewControllerB,因此请使用

#import "ViewControllerB.h"


然后在你想加载视图的地方。 didSelectRowAtIndex或某些 IBAction,需要先在 ViewControllerB中设置属性,然后再将其推入导航堆栈。

ViewControllerB *viewControllerB = [[ViewControllerB alloc] initWithNib:@"ViewControllerB" bundle:nil];
viewControllerB.isSomethingEnabled = YES;
[self pushViewController:viewControllerB animated:YES];


这会将 isSomethingEnabled中的 ViewControllerB设置为 BOOLYES


使用Segues转发数据

如果使用情节提要,则很有可能使用segues,并且需要此过程将数据转发。这与上面的类似,但是不是在推送视图控制器之前传递数据,而是使用一种称为

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender


因此,要将 BOOLViewControllerA传递到 ViewControllerB,我们将执行以下操作:


ViewControllerB.h中为 BOOL创建一个属性

@property (nonatomic, assign) BOOL isSomethingEnabled;

ViewControllerA中,您需要介绍一下 ViewControllerB,因此请使用

#import "ViewControllerB.h"

在情节提要中从 ViewControllerAViewControllerB创建一个序列,并为其指定标识符,在本示例中,我们将其称为 "showDetailSegue"
接下来,我们需要将方法添加到执行任何segue时要调用的 ViewControllerA上,因此,我们需要检测调用了哪个segue,然后执行某些操作。在我们的示例中,我们将检查 "showDetailSegue",如果执行了,我们会将 BOOL值传递给 ViewControllerB

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:@"showDetailSegue"]){
ViewControllerB *controller = (ViewControllerB *)segue.destinationViewController;
controller.isSomethingEnabled = YES;
}
}


如果您将视图嵌入导航控制器中,则需要将上面的方法稍微更改为以下方法

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:@"showDetailSegue"]){
UINavigationController *navController = (UINavigationController *)segue.destinationViewController;
ViewControllerB *controller = (ViewControllerB *)navController.topViewController;
controller.isSomethingEnabled = YES;
}
}


这会将 isSomethingEnabled中的 ViewControllerB设置为 BOOLYES


传回数据

要将数据从 ViewControllerB传递回 ViewControllerA,您需要使用协议和委托或块,后者可用作回调的松散耦合机制。

为此,我们将使 ViewControllerA成为 ViewControllerB的委托。这允许 ViewControllerB将消息发送回 ViewControllerA,使我们能够将数据发送回。

为了使 ViewControllerA成为 ViewControllerB的委托,它必须符合我们必须指定的 ViewControllerB协议。这告诉 ViewControllerA它必须实现哪些方法。


ViewControllerB.h中,在 #import之下,但在 @interface之上,指定协议。

@class ViewControllerB;

@protocol ViewControllerBDelegate <NSObject>
- (void)addItemViewController:(ViewControllerB *)controller didFinishEnteringItem:(NSString *)item;
@end

接下来仍然在 ViewControllerB.h中,您需要设置 delegate属性并在 ViewControllerB.m中进行合成

@property (nonatomic, weak) id <ViewControllerBDelegate> delegate;

ViewControllerB中,当我们弹出视图控制器时,在 delegate上调用一条消息。

NSString *itemToPassBack = @"Pass this value back to ViewControllerA";
[self.delegate addItemViewController:self didFinishEnteringItem:itemToPassBack];

ViewControllerB就是这样。现在在 ViewControllerA.h中,告诉 ViewControllerA导入 ViewControllerB并遵守其协议。

#import "ViewControllerB.h"

@interface ViewControllerA : UIViewController <ViewControllerBDelegate>

ViewControllerA.m中,根据我们的协议实施以下方法

- (void)addItemViewController:(ViewControllerB *)controller didFinishEnteringItem:(NSString *)item
{
NSLog(@"This was returned from ViewControllerB %@",item);
}

在将 viewControllerB推入导航堆栈之前,我们需要告诉 ViewControllerB ViewControllerA是它的委托,否则我们将得到一个错误。

ViewControllerB *viewControllerB = [[ViewControllerB alloc] initWithNib:@"ViewControllerB" bundle:nil];
viewControllerB.delegate = self
[[self navigationController] pushViewController:viewControllerB animated:YES];





参考文献


《 View Controller编程指南》中的 Using Delegation to Communicate With Other View Controllers
Delegate Pattern


NS通知中心
这是传递数据的另一种方式。

// add observer in controller(s) where you want to receive data
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleDeepLinking:) name:@"handleDeepLinking" object:nil];

-(void) handleDeepLinking:(NSNotification *) notification {
id someObject = notification.object // some custom object that was passed with notification fire.
}

// post notification
id someObject;
[NSNotificationCenter.defaultCenter postNotificationName:@"handleDeepLinking" object:someObject];


将数据从一个类传递回另一个类(一个类可以是任何控制器,网络/会话管理器,UIView子类或任何其他类)

块是匿名函数。

本示例将数据从控制器B传递到控制器A

定义一个块

@property void(^selectedVoucherBlock)(NSString *); // in ContollerA.h


添加块处理程序(侦听器)
需要值的地方(例如,需要ControllerA中的API响应,或者需要A上的ContorllerB数据)

// in ContollerA.m

- (void)viewDidLoad {
[super viewDidLoad];
__unsafe_unretained typeof(self) weakSelf = self;
self.selectedVoucherBlock = ^(NSString *voucher) {
weakSelf->someLabel.text = voucher;
};
}


转到控制器B

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
ControllerB *vc = [storyboard instantiateViewControllerWithIdentifier:@"ControllerB"];
vc.sourceVC = self;
[self.navigationController pushViewController:vc animated:NO];


火块

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath: 
(NSIndexPath *)indexPath {
NSString *voucher = vouchersArray[indexPath.row];
if (sourceVC.selectVoucherBlock) {
sourceVC.selectVoucherBlock(voucher);
}
[self.navigationController popToViewController:sourceVC animated:YES];
}


Another Working Example for Blocks

关于ios - 在 View Controller 之间传递数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55800392/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com