如何在iPhone上的UIViewControllers之间共享对象?

时间:2009-07-14 07:17:38

标签: iphone objective-c delegates uiviewcontroller

我的应用程序是一个标签栏应用程序,每个标签都有一个单独的视图控制器。

我的第一个视图控制器(A)中有一个对象,其中包含我存储的所有应用程序数据(请忽略NSUserDefaults),当我按下按钮时,第二个视图控制器(B)需要访问该数据。我怎样才能以最佳方式实现这一目标?

5 个答案:

答案 0 :(得分:32)

您拥有的一个选项是将日期模型声明为应用代理的实例变量(如其他评论者所述)。

不是按照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];

另见this关于单身人士的堆栈溢出讨论。

答案 1 :(得分:8)

我见过的最常见的方法是在app delegate中设置你想要访问的东西,然后在其他地方引用它:

MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate]; 
myStuff = appDelegate.stuff;

在app delegate中,设置一个stuff变量并像往常一样使用@property和@synthesize。

有些人说这不是一个好方法,因为它与使用全局变量相同,但它很常见。

答案 2 :(得分:5)

我喜欢创建一个顶级的Model类,它是一个单例,包含我可能需要的所有元素。

使用Apple示例中常见的水合物/脱水模式,使用顶级加载方法(仅使用数据库键填充对象)也很有帮助。

应用代理中的典型用法很简单,

[[MyModel sharedModel] load];

然后在视图控制器中:

NSArray *myThing1s = [[MyModel sharedModel] thing1s];
NSArray *myThing2s = [[MyModel sharedModel] thing2s];

然后你可以迭代你的thing1s和thing2s,当你需要细节时,你可以打电话

[myThing1 hydrate];

将填充对象。

当然,您可能希望使用CoreData来管理从3.0开始的持久性。

答案 3 :(得分:3)

我总是创建一个名为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]

答案 4 :(得分:0)

两个视图控制器都应引用第三个对象(C)作为其dataSource;该对象(C)包含所有存储的应用程序数据。

在这种情况下,C将是MVC中的M.

向每个ViewControllers添加以下声明:

// SomeViewController.h
// Before @interface

@class MyDataSource;

// In the interface

IBOutlet MyDataSource *datasource;
@property(retain) IBOutlet MyDataSource *datasource;
相关问题