我对iOS和Objective-C以及整个MVC范式都是新手,我一直坚持以下几点:
我有一个充当数据输入表单的视图,我想让用户选择多个产品。产品列在另一个具有UITableViewController的视图中,我已启用多个选项。
如何将数据从一个视图传输到另一个视图?我会将UITableView上的选择保存在一个数组中,但如何将其传递回上一个数据输入表单视图,以便在提交表单时将其与其他数据一起保存到核心数据?
我在网上冲浪,看到一些人在应用程序委托中声明了一个数组。我读了一些关于单态的东西,但我不明白这些是什么,我读了关于创建数据模型的东西。
正确的执行方式是什么?我将如何执行?
我在这个解决方案中搜索了很长时间,终于找到了它
@interface SecondViewController: UIviewController
{
NSMutableArray *myAray;
CustomObject *object;
}
现在在实现文件中,为这些对象分配内存,如下所示:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
// Custom initialization
myAray=[[NSMutableArray alloc] init];
object=[[CustomObject alloc] init];
}
return self;
}
现在您已经为数组和对象分配了内存。现在,您可以在推送此ViewController之前填充该内存。
转到SecondViewController.h并编写两个方法:
-(void)setMyArray:(NSArray *)_myArray;
-(void)setMyObject:(CustomObject *)_myObject;
在实现文件中,您可以实现以下功能:
-(void)setMyArray:(NSArray *)_myArray
{
[myArra addObjectsFromArray:_myArray];
}
-(void)setMyObject:(CustomObject *)_myObject
{
[object setCustomObject:_myObject];
}
期望CustomObject必须具有setter函数。
现在你的基本工作完成了。转到要推动SecondViewController的位置,执行以下操作:
SecondViewController *secondView= [[SecondViewController alloc] initWithNibName:@"SecondViewController " bundle:[NSBundle MainBundle]] ;
[secondView setMyArray:ArrayToPass];
[secondView setMyObject:objectToPass];
[self.navigationController pushViewController:secondView animated:YES ];
注意拼写错误。
这个问题有很多答案,提供了许多不同的方法来执行视图控制器通信,这些方法确实有效,但我没有看到任何地方提到哪种方法实际上最好使用,哪种方法最好避免。
在实践中,我认为只建议几个解决方案:
要向前传递数据:使用情节提要和片段时,重写UIViewController的prepare(for:sender:)方法执行视图控制器转换时通过初始化器或财产传递数据困难代码向后传递数据更新应用程序共享状态(您可以使用上述任一方法在视图控制器之间传递该状态)使用委托使用放松段
我建议不要使用的解决方案:
直接引用上一个控制器,而不是使用委派通过单例共享数据通过应用程序代理传递数据通过用户默认值共享数据通过通知传递数据
这些解决方案虽然在短期内有效,但引入了太多的依赖性,这将扰乱应用程序的架构,并在以后产生更多问题。
对于感兴趣的人,我写了一些文章,更深入地讨论了这些问题,并强调了各种缺点:
iOS视图控制器如何相互通信如何构建iOS应用程序的代码通过一个实例了解iOS开发的核心架构原则
我更喜欢在没有代表和片段的情况下进行。它可以通过自定义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?()
}
}
新闻视图控制器
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tbl_View deselectRowAtIndexPath:indexPath animated:YES];
News *newsObj = [newstitleArr objectAtIndex:indexPath.row];
NewsDetailViewController *newsDetailView = [[NewsDetailViewController alloc] initWithNibName:@"NewsDetailViewController" bundle:nil];
newsDetailView.newsHeadlineStr = newsObj.newsHeadline;
[self.navigationController pushViewController:newsDetailView animated:YES];
}
NewsDetailViewController.h
@interface NewsDetailViewController : UIViewController
@property(nonatomic,retain) NSString *newsHeadlineStr;
@end
NewsDetailViewController.m
@synthesize newsHeadlineStr;