我最近询问a question我在UIViewControllers
上错误使用实例变量的问题。我得到的答案揭示了另一个基本问题:我认为我可能也会使用UIViewControllers
所有错误。
我的典型故事板看起来像这样:
如您所见,每个视图控制器都有一个自定义类。其中一个自定义类可能如下所示:
// SecondViewController.h
#import <UIKit/UIKit.h>
#import "MasterViewController.h"
@interface SecondViewController : MasterViewController
@property (strong, nonatomic) NSData *incomingData;
@end
// SecondViewController.m
#import "SecondViewController.h"
#import "ThirdViewController.h"
@interface SecondViewController ()
@end
@implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
// do stuff with data, then pass it on to next view controller.
}
@end
每个视图控制器都是MasterViewController
的子类。在MasterViewController
中,我通常会将全局内容放在用户状态验证中。这样,应用程序中的每个视图控制器都可以验证用户状态,而无需每次重新实现它。
关于那个incomingData
属性...我不确定如何在UIViewControllers
之间传递数据而不使用自定义类上的属性...因此有三个单独的自定义类,每个一个人没那么做。
所以这里对我来说是阴暗的......
我当前的系统大部分都在工作,但是当我有很多很多视图控制器时,它们都会变得笨拙,每个视图控制器都有自己的自定义类。
答案 0 :(得分:0)
你在这里有强耦合,这被认为是一件坏事。
假设你想要创建一个新的应用程序,并且想要从旧的应用程序中复制一个视图控制器,那么你将很难修改很多东西。
目标是实现弱耦合,这意味着项目中的每个类都可以彼此独立工作。
答案 1 :(得分:0)
您可以将数据存储为App Delegate上的属性,这是一个单例,因此您可以使用AppDelegate *appDelegate=[UIApplication sharedApplication].delegate;
从任何类中获取引用。或者,您可以定义一个新的单例对象来存储数据。
您使用的模式是依赖注入,许多人更喜欢单一模式。
如果所有视图控制器都继承自同一个超类(MasterViewController)并且都具有相同的属性,那么您只需在超类中定义属性即可。
答案 2 :(得分:0)
显然,您可能已经完成的第一步,以及您是否完全掌握,是真正理解模型 - 视图 - 控制器模式。我用快速谷歌搜索做的一个非常好的教程是:http://codewithchris.com/how-to-make-iphone-apps-mvc-one-pattern-to-rule-them-all/。
接下来我建议你的控制器不需要是UIViewController以外的任何子类。视图层次结构和类层次结构之间存在差异。在故事板中,您将概述视图层次结构 - 哪个视图/控制器指向下一个视图/控制器。他们都可以独立。即使不是彼此的子类,也不是先前控制器的子类,它们仍然可以传递数据。
您仍然可以直接通过属性传递数据。为什么不更具体地说明需要发送哪些数据?而不是发送通用NSData blob,而是指定一个控制器需要告诉下一个控制器。例如,如果您要将用户名从一个用户名传递到另一个用户名,请使用:
@property (nonatomic, strong) NSString *username;
对于第二个控制器,在第一个控制器中,设置它:
self.secondController.username = @"my name";
如果从第二个控制器到第三个控制器,您不需要用户名,请不要将其作为第三个控制器的属性。也许第三个控制器只显示一个数字:
@property (nonatomic, strong) NSNumber *someNumber;
从第二个控制器,只需设置其值:
self.thirdController.someNumber = @5;
现在,我喜欢使用一些全局变量和方法。当你有不需要实例化的辅助类时,这些有时很有用。一种方法是只有一个类变量:
FirstController.h:
+(NSString *)defaultName;
FirstController.m
+(NSString *)defaultName {
return @"Default";
}
然后在第二个控制器中,您可以执行类似
的操作self.username = [FirstController defaultName]
还有其他模式,比如委托模式,第二个控制器询问其委托(第一个控制器)用户名应该是什么:
self.username = [self.delegate username];
但为此你必须建立一个协议。 Ray Wenderlich通常有非常好的教程:http://www.raywenderlich.com/46988/ios-design-patterns