我对iOS和Objective-C以及整个MVC范式都是新手,我一直坚持以下几点:
我有一个充当数据输入表单的视图,我想让用户选择多个产品。产品列在另一个具有UITableViewController的视图中,我已启用多个选项。
如何将数据从一个视图传输到另一个视图?我会将UITableView上的选择保存在一个数组中,但如何将其传递回上一个数据输入表单视图,以便在提交表单时将其与其他数据一起保存到核心数据?
我在网上冲浪,看到一些人在应用程序委托中声明了一个数组。我读了一些关于单态的东西,但我不明白这些是什么,我读了关于创建数据模型的东西。
正确的执行方式是什么?我将如何执行?
我更喜欢在没有代表和片段的情况下进行。它可以通过自定义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?()
}
}
我建议使用块/闭包和自定义构造函数。
假设您必须将字符串从FirstViewController传递到SecondViewController。
您的第一个视图控制器。
class FirstViewController : UIViewController {
func moveToViewControllerB() {
let second_screen = SecondViewController.screen(string: "DATA TO PASS", call_back: {
[weak self] (updated_data) in
///This closure will be called by second view controller when it updates something
})
self.navigationController?.pushViewController(second_screen, animated: true)
}
}
第二个视图控制器
class SecondViewController : UIViewController {
var incoming_string : String?
var call_back : ((String) -> Void)?
class func screen(string: String?, call_back : ((String) -> Void)?) -> SecondViewController {
let me = SecondViewController(nibName: String(describing: self), bundle: Bundle.main);
me.incoming_string = string
me.call_back = call_back
return me
}
// Suppose its called when you have to update FirstViewController with new data.
func updatedSomething() {
//Executing block that is implemented/assigned by the FirstViewController.
self.call_back?("UPDATED DATA")
}
}
我目前正在通过一个名为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];
}