我的应用程序是一个标签栏应用程序,每个标签都有一个单独的视图控制器。
我的第一个视图控制器 (A) 中有一个对象,其中包含我存储的所有应用程序数据(请忽略 NSUserDefaults),当我按下一个按钮时,第二个视图控制器 (B) 需要访问它。我怎样才能以最好的方式实现这一目标?
我的应用程序是一个标签栏应用程序,每个标签都有一个单独的视图控制器。
我的第一个视图控制器 (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;
在应用程序委托中,设置一个 stuff 变量并像往常一样使用@property 和@synthesize。
有人说这不是一个好方法,因为它与使用全局变量相同,但它很常见。
我喜欢创建一个顶级模型类,它是一个单例并包含我可能需要的所有元素。
使用 Apple 示例中常见的水合物/脱水模式,为它提供一个仅使用 db 键填充对象的顶级加载方法也很有帮助。
应用程序委托中的典型用法很简单,
[[MyModel sharedModel] load];
然后在视图控制器中:
NSArray *myThing1s = [[MyModel sharedModel] thing1s];
NSArray *myThing2s = [[MyModel sharedModel] thing2s];
然后你可以迭代你的thing1s和thing2s,当你需要细节时,你可以打电话
[myThing1 hydrate];
这将填充对象。
当然,您可能希望使用 CoreData 来管理从 3.0 开始的持久性。
我总是创建一个名为DataModel
并使用它的特殊对象 singleton sharedInstance
。
然后这个对象保存所有与应用程序相关的数据。无需访问可怕的 appDelegate
.
数据模型.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
数据模型.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。
向每个 ViewController 添加以下声明:
// SomeViewController.h
// Before @interface
@class MyDataSource;
// In the interface
IBOutlet MyDataSource *datasource;
@property(retain) IBOutlet MyDataSource *datasource;