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

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

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

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

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


当前回答

要将数据从一个视图控制器(VC)发送到另一个,请使用以下简单方法:

YourNextVC *nxtScr = (YourNextVC*)[self.storyboard  instantiateViewControllerWithIdentifier:@"YourNextVC"];//Set this identifier from your storyboard

nxtScr.comingFrom = @"PreviousScreen"l
[self.navigationController nxtScr animated:YES];

其他回答

要将数据从一个视图控制器(VC)发送到另一个,请使用以下简单方法:

YourNextVC *nxtScr = (YourNextVC*)[self.storyboard  instantiateViewControllerWithIdentifier:@"YourNextVC"];//Set this identifier from your storyboard

nxtScr.comingFrom = @"PreviousScreen"l
[self.navigationController nxtScr animated:YES];

使用通知中心将数据从一个视图传递到另一个视图。

观察者-收听者模式效果最好。另一种解决方法是在两个类中创建相同的对象。

在类1中创建类2对象。访问要传递的数据对象,设置它们,然后按下视图控制器。

我更喜欢在没有代表和片段的情况下进行。它可以通过自定义init或设置可选值来完成。

1.自定义初始化

class ViewControllerA: UIViewController {
  func openViewControllerB() {
    let viewController = ViewControllerB(string: "Blabla", completionClosure: { success in
      print(success)
    })
    navigationController?.pushViewController(animated: true)
  }
}

class ViewControllerB: UIViewController {
  private let completionClosure: ((Bool) -> Void)
  init(string: String, completionClosure: ((Bool) -> Void)) {
    self.completionClosure = completionClosure
    super.init(nibName: nil, bundle: nil)
    title = string
  }

  func finishWork() {
    completionClosure()
  }
}

2.可选变量

class ViewControllerA: UIViewController {
  func openViewControllerB() {
    let viewController = ViewControllerB()
    viewController.string = "Blabla"
    viewController.completionClosure = { success in
      print(success)
    }
    navigationController?.pushViewController(animated: true)
  }
}

class ViewControllerB: UIViewController {
  var string: String? {
    didSet {
      title = string
    }
  }
  var completionClosure: ((Bool) -> Void)?

  func finishWork() {
    completionClosure?()
  }
}

使用通知中心

对于Swift 3

let imageDataDict:[String: UIImage] = ["image": image]

// Post a notification
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "notificationName"), object: nil, userInfo: imageDataDict)
// `default` is now a property, not a method call

// Register to receive notification in your class
NotificationCenter.default.addObserver(self, selector: #selector(self.showSpinningWheel(_:)), name: NSNotification.Name(rawValue: "notificationName"), object: nil)

// Handle notification
func showSpinningWheel(_ notification: NSNotification) {
    print(notification.userInfo ?? "")
    if let dict = notification.userInfo as NSDictionary? {
        if let id = dict["image"] as? UIImage {
            // Do something with your image
        }
    }
}

对于Swift 4

let imageDataDict:[String: UIImage] = ["image": image]

// Post a notification
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "notificationName"), object: nil, userInfo: imageDataDict)
// `default` is now a property, not a method call

// Register to receive notification in your class
NotificationCenter.default.addObserver(self, selector: #selector(self.showSpinningWheel(_:)), name: NSNotification.Name(rawValue: "notificationName"), object: nil)

// Handle notification
@objc func showSpinningWheel(_ notification: NSNotification) {
    print(notification.userInfo ?? "")
    if let dict = notification.userInfo as NSDictionary? {
        if let id = dict["image"] as? UIImage {
            // Do something with your image
        }
    }
}

我目前正在通过一个名为MCViewFactory的项目为这个问题的开源解决方案做出贡献,这个项目可以在这里找到:

Manticore iOS视图工厂

其想法是模仿Android的意图范式,使用全局工厂来管理您正在查看的视图,并使用“意图”在视图之间切换和传递数据。所有文档都在GitHub页面上,但这里有一些亮点:

初始化工厂时,在.XIB文件中设置所有视图并在应用程序委托中注册它们。

// Register activities

MCViewFactory *factory = [MCViewFactory sharedFactory];

// The following two lines are optional.
[factory registerView:@"YourSectionViewController"];

现在,在视图控制器(VC)中,只要您想移动到新的VC并传递数据,就可以创建一个新的意图并将数据添加到其字典(savedInstanceState)中。然后,只需设置工厂的当前意图:

MCIntent* intent = [MCIntent intentWithSectionName:@"YourSectionViewController"];
[intent setAnimationStyle:UIViewAnimationOptionTransitionFlipFromLeft];
[[intent savedInstanceState] setObject:@"someValue" forKey:@"yourKey"];
[[intent savedInstanceState] setObject:@"anotherValue" forKey:@"anotherKey"];
// ...
[[MCViewModel sharedModel] setCurrentSection:intent];

所有符合此要求的视图都需要是MCViewController的子类,它允许您重写新的onResume:方法,允许您访问传入的数据。

-(void)onResume:(MCIntent *)intent {
    NSObject* someValue = [intent.savedInstanceState objectForKey:@"yourKey"];
    NSObject* anotherValue = [intent.savedInstanceState objectForKey:@"anotherKey"];

    // ...

    // Ensure the following line is called, especially for MCSectionViewController
    [super onResume:intent];
}