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

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

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

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

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


当前回答

在下一个视图controller.h文件中创建属性,并定义getter和setter。

在NextVC上的NextVC.h中添加此属性:

@property (strong, nonatomic) NSString *indexNumber;

Add

@综合索引编号;在NextVC.m中

最后一个

NextVC *vc = [[NextVC alloc]init];

vc.indexNumber = @"123";

[self.navigationController vc animated:YES];

其他回答

在为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视图控制器中的委托属性。

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

这个问题有很多答案,提供了许多不同的方法来执行视图控制器通信,这些方法确实有效,但我没有看到任何地方提到哪种方法实际上最好使用,哪种方法最好避免。

在实践中,我认为只建议几个解决方案:

要向前传递数据:使用情节提要和片段时,重写UIViewController的prepare(for:sender:)方法执行视图控制器转换时通过初始化器或财产传递数据困难代码向后传递数据更新应用程序共享状态(您可以使用上述任一方法在视图控制器之间传递该状态)使用委托使用放松段

我建议不要使用的解决方案:

直接引用上一个控制器,而不是使用委派通过单例共享数据通过应用程序代理传递数据通过用户默认值共享数据通过通知传递数据

这些解决方案虽然在短期内有效,但引入了太多的依赖性,这将扰乱应用程序的架构,并在以后产生更多问题。

对于感兴趣的人,我写了一些文章,更深入地讨论了这些问题,并强调了各种缺点:

iOS视图控制器如何相互通信如何构建iOS应用程序的代码通过一个实例了解iOS开发的核心架构原则

我找到了最简单、最优雅的版本,带有传递块。让我们将等待返回数据的视图控制器命名为“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);

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

您可以创建一个从源视图控制器到目标视图控制器的推送段,并提供如下标识符名称。

您必须像这样执行didselectRowAt的segue。

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    performSegue(withIdentifier: "segue", sender: self)
}

您可以从下面的函数传递选定项的数组。

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let index = CategorytableView.indexPathForSelectedRow
    let indexNumber = index?.row
    print(indexNumber!)
    let VC = segue.destination as! AddTransactionVC
    VC.val = CategoryData[indexNumber!] . // Here you can pass the entire array instead of an array element.
}

您必须检查目标viewcontroller的viewdidload中的值,然后将其存储到数据库中。

override func viewDidLoad{
    if val != ""{
        btnSelectCategory.setTitle(val, for: .normal)
    }
}

经过更多的研究,协议和代表似乎是正确的/苹果首选的方式。

我最终使用了这个示例(在iPhone开发SDK中):

在视图控制器和其他对象之间共享数据

它工作得很好,允许我在视图之间前后传递字符串和数组。