我对iOS和Objective-C以及整个MVC范式都是新手,我一直坚持以下几点:

我有一个充当数据输入表单的视图,我想让用户选择多个产品。产品列在另一个具有UITableViewController的视图中,我已启用多个选项。

如何将数据从一个视图传输到另一个视图?我会将UITableView上的选择保存在一个数组中,但如何将其传递回上一个数据输入表单视图,以便在提交表单时将其与其他数据一起保存到核心数据?

我在网上冲浪,看到一些人在应用程序委托中声明了一个数组。我读了一些关于单态的东西,但我不明白这些是什么,我读了关于创建数据模型的东西。

正确的执行方式是什么?我将如何执行?


当前回答

这是一个非常棒的教程,适合任何想要的人。下面是示例代码:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"myIdentifer]) {
        NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
        myViewController *destViewController = segue.destinationViewController;
        destViewController.name = [object objectAtIndex:indexPath.row];
    }
}

其他回答

有三种类型用于将数据从一个ViewController传递到另一个ViewControlViewController。

程序性地赛格牌手表用户默认值

演示项目链接此处-https://github.com/kamanijasmin13/Swift-Pass-data-between-viewcontrollers

程序性地

赛格牌手表

用户默认值

演示项目链接此处-https://github.com/kamanijasmin13/Swift-Pass-data-between-viewcontrollers

我找到了最简单、最优雅的版本,带有传递块。让我们将等待返回数据的视图控制器命名为“A”,将返回的视图控制器称为“B”。在本例中,我们希望获得两个值:第一个是Type1,第二个是Type2。

假设我们使用Storyboard,第一个控制器设置回调块,例如在segue准备期间:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.destinationViewController isKindOfClass:[BViewController class]])
    {
        BViewController *viewController = segue.destinationViewController;

        viewController.callback = ^(Type1 *value1, Type2 *value2) {
            // optionally, close B
            //[self.navigationController popViewControllerAnimated:YES];

            // let's do some action after with returned values
            action1(value1);
            action2(value2);
        };

    }
}

和“B”视图控制器应声明回调属性BViewController.h:

// it is important to use "copy"
@property (copy) void(^callback)(Type1 *value1, Type2 *value2);

在实现文件BViewController.m中,当我们有了所需的值以返回回调时,应该调用:

if (self.callback)
    self.callback(value1, value2);

需要记住的一点是,使用块通常需要管理强引用和弱引用,如这里所述

这里有一个更简单的方法。

只需使用全局变量。声明传递给下一个类所需的对象或变量。

例如,我们有两个类-类A和类B。

在类A中,通常包含:

#import "classA.h"

@interface classA()

@end

@implementation classA

-(void)viewDidLoad
{
    ...
}
-(void)didReceiveMemoryWarning
{
    ...
}

B类包含:

#import "classB.h"

@interface classB()

@end

@implementation classB

-(void)viewWillLoad
{
    ...
}
-(void)didReceiveMemoryWarning
{
    ...
}

现在,将第二个类classB导入classA:

#import "classA.h"
#import "classB.h"  // --- Import classB to classA.
@interface classA()

@end

@implementation classA

-(void)viewDidLoad
{
    ...
}
-(void)didReceiveMemoryWarning
{
    ...
}

现在我们有一座桥去二等B班。现在,要将变量或对象声明为全局变量,请在第一个类的.m文件中声明它,如下所示:

在A.h类中

#import "classA.h"
#import "classB.h"
@interface classA()

@end
NSString *temp;  // ---- Declare any object/variable as global.
@implementation classA

-(void)viewDidLoad
{
    ...
    temp=@"Hello";
    ...
}
-(void)didReceiveMemoryWarning
{
    ...
}

这里,对象temp是NSString类的全局对象。要访问任何类中的全局对象或变量,只需在第二个类中重新声明对象或变量。例如,如下所示:

在B.m类中

#import "classB.h"

@interface classB()

@end
extern NSString *temp;  //----use `extern` keyword for using the global object/variable in classB that was declared in classA.
@implementation classB

-(void)viewDidLoad
{
    ...
    LabeL.text=temp;
    ...
}
-(void)didReceiveMemoryWarning
{
    ...
}

现在,第二个类可以访问该值。易于理解的此方法可用于任意数量的类。

注:

您应该将第二个类的.h文件导入到第一个类。但不需要进口将第一类的.h文件转换为第二类。

记住那座桥。如果有一座桥,它应该可以从两边走。

MVC中的M代表“模型”,而在MVC范式中,模型类的作用是管理程序的数据。模型与视图相反——视图知道如何显示数据,但它不知道如何处理数据,而模型知道如何使用数据,但不知道如何显示。模型可能很复杂,但不一定如此——应用程序的模型可能与字符串或字典数组一样简单。

控制器的作用是在视图和模型之间进行调解。因此,它们需要对一个或多个视图对象和一个或更多模型对象的引用。假设您的模型是一个字典数组,每个字典代表表中的一行。应用程序的根视图显示该表,它可能负责从文件加载数组。当用户决定向表中添加新行时,他们点击某个按钮,控制器将创建一个新的(可变的)字典并将其添加到数组中。为了填充该行,控制器创建一个详细视图控制器并为其提供新字典。详细视图控制器填充字典并返回。字典已经是模型的一部分,因此不需要发生其他任何事情。

在为iOS创建应用程序时,您必须始终遵循MVC概念。

有两种情况下,您可能希望将数据从ViewController传递到另一个:

当层次结构中有一个“A”ViewContoller,并且您希望将一些数据发送到“B”,这是下一个视图控制器。在这种情况下,您必须使用Segue。只需为segue设置一个标识符,然后在“A”VC中编写以下代码:override func prepare(segue:UIStoryboardSegue,sender:Any?){如果segue.identifier==“A到B segue-identifier”{让bViewController=segue.destination为!UIDocumentBrowserViewControllerbViewController.data=某些数据}}当有一个A将B作为模态(或嵌入)打开时。现在,B视图控制器应该对其父对象视而不见。因此,将数据发送回A的最佳方法是使用委派。在B视图控制器和委托属性中创建委托协议。因此,B将向其代表报告(发送数据)。在A视图控制器中,我们实现了B视图控制器的委托协议,并将在prepare(forSegue:)方法中将self设置为B视图控制器中的委托属性。

这就是它应该正确实现的方式。