在第一个视图控制器(A)中有一个对象,其中包含所有存储的应用程序数据(请忽略NSUserDefaults),需要在按下第二个视图控制器(B)上的按钮时由其访问。如何以最佳方式实现这一点?
你可以选择将日期模型声明为应用程序委托的实例变量(正如其他评论者所提到的)。
与 nevan 建议的引用应用程序委托不同,另一种选择是为您的视图控制器类(A 和 B)添加一个数据模型属性。
假设您想在视图控制器之间共享数据模型对象,您可以为每个视图控制器添加一个属性:
@interface AViewController : UIViewController {
MyDataModel *model;
}
@property (nonatomic, retain) MyDataModel *model;
@end
@interface BViewController : UIViewController {
MyDataModel *model;
}
@property (nonatomic, retain) MyDataModel *model;
@end
当您初始化视图控制器时,可以将此属性设置为之前初始化的对象上下文。
您提到了选项卡栏控制器。如果您的视图控制器通过IB连接,那么您只需要在选项卡栏控制器显示之前,在应用程序委托的applicationDidFinishLaunching:
方法中设置这些参数:
@interface MyAppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate>
{
MyDataModel *model;
AViewController *aViewController;
BViewController *bViewController;
...
}
@property (retain) IBOutlet AViewController *aViewController;
@property (retain) IBOutlet BViewController *aViewController;
@end
@implementation MyAppDelegate
...
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
...
aViewController.model = model;
bViewController.model = model;
[window addSubview:tabBarController.view];
[window makeKeyAndVisible];
}
别忘了在你的视图控制器的dealloc
方法中释放模型。
另一种方法是使用单例对象。一个简单的单例示例:
@interface MyDataModel : NSObject
{
}
+ (MyDataModel *) sharedDataModel;
@end
@implementation MyDataModel
static MyDataModel *sharedDataModel = nil;
+ (MyDataModel *) sharedDataModel
{
@synchronized(self)
{
if (sharedDataModel == nil)
{
sharedDataModel = [[MyDataModel alloc] init];
}
}
return sharedDataModel;
}
@end
您可以通过类似以下的方式从所有视图控制器访问此数据模型:
MyDataModel *model = [MyDataModel sharedDataModel];
请参见此堆栈溢出讨论关于单例模式。
我见过最常用的做法是在应用程序委托中设置你想要访问的内容,然后在其他地方引用它,就像这样:
MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
myStuff = appDelegate.stuff;
我喜欢创建一个顶层的Model类,作为单例模式,并包含我可能需要的所有元素。
同时为其提供一个顶级的load方法,使用在Apple示例中常见的hydrate/dehydrate模式,仅用db keys填充对象。
在应用程序委托中的典型用法只需简单地:
[[MyModel sharedModel] load];
然后在视图控制器中:
NSArray *myThing1s = [[MyModel sharedModel] thing1s];
NSArray *myThing2s = [[MyModel sharedModel] thing2s];
[myThing1 hydrate];
这将填充该对象。
当然,从3.0开始,您可能希望使用CoreData来管理持久性。
我经常创建一个特殊的对象称为 DataModel
,并使用它的单例 sharedInstance
。
然后这个对象保存所有与应用相关的数据。无需访问 可怕的 appDelegate
。
DataModel.h
#import <Foundation/Foundation.h>
@class MyClass1, MyClass2;
@interface DataModel : NSObject
@property (copy, nonatomic) NSString *aString;
@property (assign) BOOL aBool;
@property (strong) MyClass1 *myObject1;
@property (strong) MyClass2 *myObject2;
+ (DataModel *)sharedModel;
@end
DataModel.m
#import "DataModel.h"
#import "Class1.h"
#import "Class2.h"
@implementation DataModel
- (id) init
{
self = [super init];
if (self)
{
_myObject1 = [[MyClass1 alloc] init];
_myObject2 = [[MyClass2 alloc] init];
aBool = NO;
aString = nil;
}
return self;
}
+ (DataModel *)sharedModel
{
static DataModel *_sharedModel = nil;
static dispatch_once_t onceSecurePredicate;
dispatch_once(&onceSecurePredicate,^
{
_sharedModel = [[self alloc] init];
});
return _sharedModel;
}
@end
因为我比较懒,所以把DataModel.h
放在application-prefix.pch
中。
这样一来,我只需调用一次就可以从应用程序的任何地方访问我的数据了。
[DataModel sharedModel]
两个视图控制器都应该引用第三个对象(C)作为它们的数据源;这个对象(C)包含了所有存储的应用程序数据。
在这种情况下,C将是MVC中的M。
向每个您的视图控制器添加以下声明:
// SomeViewController.h
// Before @interface
@class MyDataSource;
// In the interface
IBOutlet MyDataSource *datasource;
@property(retain) IBOutlet MyDataSource *datasource;