Как я могу разделить объект между UIViewControllers на iPhone? - PullRequest
23 голосов
/ 14 июля 2009

Мое приложение - это приложение панели вкладок, с отдельным контроллером представления для каждой вкладки.

У меня есть объект в моем первом контроллере представления (A), который содержит все мои сохраненные данные приложения (для этого не обращайте внимания на NSUserDefaults), к которому должен обращаться второй контроллер представления (B), когда я нажимаю на него кнопку. Как я могу добиться этого наилучшим образом?

Ответы [ 5 ]

32 голосов
/ 14 июля 2009

Один из вариантов, который у вас есть, - это объявить вашу модель даты как переменные экземпляра вашего делегата приложения (как упоминалось другими комментаторами).

Вместо того, чтобы ссылаться на делегат приложения, как предлагает 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];

См. Также обсуждение переполнения стека о синглетонах.

8 голосов
/ 14 июля 2009

Самый распространенный способ, который я видел, это настроить то, к чему вы хотите получить доступ в делегате приложения, и ссылаться на него в других местах, например так:

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

В делегате приложения установите переменную stuff и, как обычно, используйте @property и @synthesize.

Некоторые люди говорят, что это не очень хороший подход, поскольку он аналогичен использованию глобальных переменных, но очень распространен.

5 голосов
/ 14 июля 2009

Мне нравится создавать класс Model высшего уровня, который является одноэлементным и содержит все элементы, которые мне могут понадобиться.

Полезно также предоставить ему метод загрузки верхнего уровня, который заполняет объекты только ключами db, используя шаблон гидрата / дегидрата, распространенный в примерах Apple.

Типичное использование в делегате приложения будет просто,

[[MyModel sharedModel] load];

А затем в контроллере вида:

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

Затем вы можете перебирать вещи thing1s и thing2s, а когда вам нужны подробности, вы можете просто позвонить

[myThing1 hydrate];

, который будет заполнять объект.

Конечно, вы, вероятно, захотите использовать CoreData для управления постоянством начиная с версии 3.0.

3 голосов
/ 24 апреля 2013

Я всегда создаю специальный объект с именем 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]
0 голосов
/ 14 июля 2009

Оба контроллера представления должны ссылаться на третий объект (C) в качестве своего источника данных; этот объект (C), содержащий все сохраненные данные приложения.

C в этом случае будет M в MVC.

Добавьте к каждому из ваших ViewControllers следующие объявления:

// SomeViewController.h
// Before @interface

@class MyDataSource;

// In the interface

IBOutlet MyDataSource *datasource;
@property(retain) IBOutlet MyDataSource *datasource;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...