Альтернатива глобальным переменным в делегате приложения - PullRequest
4 голосов
/ 03 октября 2011

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

Однако я не уверен, является ли это хорошим или плохим дизайнерским решением.Я думаю, что, поскольку это некритическая часть информации (просто поплавок), при ее глобальном хранении не будет никакого вреда.Но мое ООП-сердце болит каждый раз, когда я говорю себе слово «глобальный».

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

Я делаю это правильно или есть более правильный способ сделать то, что я делаю?

Ответы [ 3 ]

2 голосов
/ 03 октября 2011

Я делаю это так, потому что позиция стрелки обновляется и используется несколькими классами.

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

Однако я не уверен, является ли это хорошим или плохим дизайнерским решением.Я думаю, что, поскольку это некритическая часть информации (просто поплавок), при ее глобальном хранении не будет никакого вреда.Но мое ООП-сердце болит каждый раз, когда я говорю себе слово «глобальный».

возможно, вы можете переместить состояние (значение с плавающей запятой) на ивар в вашем спидометре?пример: вы, скорее всего, отображаете только один вид спидометра: имеет ли смысл добавлять его к модели вида?или, может быть, его контроллер?(да, немного сложнее привести более конкретный пример без исходного кода)

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

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

Я делаю это правильно или есть более правильный способ делать то, что я делаю?

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

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

  • не использовать синглтон.велики шансы, что вы перепишете его, когда захотите снова его использовать.это сахарная шуба, что некрасиво.если ваш контроллер приложения находится в беспорядке из-за слишком большого глобального состояния, по крайней мере тот факт, что у вас слишком много глобального состояния, будет очевиден.
  • удерживайте ваше глобальное состояние в контроллере приложения.Контроллер вашего приложения отвечает за его инициализацию, время жизни и доступ.
  • предоставляет это состояние зависимостям, поэтому они не ссылаются (или даже не знают) о глобальном домене (контроллере приложения).тогда вы можете свести к минимуму влияние.

также существует четкая разница между глобальным состоянием и состоянием приложения / выполнения.глобальное состояние должно быть устранено.Состояние выполнения - это не глобальное состояние, а локализованный контекст выполнения.Состояние выполнения может быть повторно введено на нужном уровне, изменено и обновлено, протестировано и, как ожидается, повторно использовано.хороший дизайн представит состояние выполнения при необходимости и на правильном уровне, избегая глобального состояния.

Обновление

Ваш образец очень близок к тому, что я себе представлял,на основании описания в ОП.Это обеспечило некоторые дополнительные особенности.Итак, приведенный ниже пример (вам понадобятся некоторые дополнения в очевидных областях, чтобы собрать все вместе) демонстрирует, как вы можете обновить интерфейсы контроллера, и в конце есть два бесплатных метода «в другом месте», которые дополнительно иллюстрируют, как их использовать:

@interface MONArrowPosition : NSObject
{
    float arrowPosition;
}

@end

@implementation MONArrowPosition

- (id)initWithPosition:(float)position
{
    self = [super init];
    if (nil != self) {
        arrowPosition = position;
    }
    return self;
}

@end

@interface MyViewController1 : UIViewController
{
    MONArrowPosition * arrowPosition; // << may actually be held by the model
}

@end

@implementation MyViewController1

- (void)applyRotation
{
    [self rotateLayer:arrow from:self.arrowPosition to:callStatus speed:METER_SPEED];
}

@end

@interface MyViewController2 : UIViewController
{
    MONArrowPosition * arrowPosition; // << may actually be held by the model
}

@end

@implementation MyViewController2

- (void)viewDidLoad
{
    [super viewDidLoad];
    /* ... */
    [self.slider addTarget:self action:@selector(sliderValueDidChange) forControlEvents:controlEvents];
}

- (void)sliderValueDidChange
{
    self.arrowPosition.arrowPosition = self.slider.value;
    [self arrowPositionDidChange];
}

@end

/* elsewhere: */
- (void)initializeArrowPosition
{
    /* The variable is set to a default of 0.0f */
    MONArrowPosition * arrowPosition = [[MONArrowPosition alloc] initWithPosition:0.0f];
    /* ... */
}

- (IBAction)someActionWhichPushesMyViewController1
{
    // depending on the flow of your app, the body of initializeArrowPosition
    // *could* be right here
    MyViewController1 * viewController = [[MyViewController1 alloc] initWithNibName:nibName bundle:bundle];
    viewController.arrowPosition = self.arrowPosition;
    /* push it */
}

и затем, если MyViewController1 нажимает MyViewController2, найти и установить положение стрелки будет легко. контроллеры представления также могут делиться некоторой информацией в моделях. с глобалом в вашем образце вы пересекаете множество реализаций, которые добавляют связывание, увеличивают зависимость и т. д., поэтому, если вы можете использовать этот подход и локализовать состояние выполнения, у вас хорошее начало. тогда вы можете использовать любое количество контроллеров представления с любым количеством позиций MONArrow, и они не будут подвержены влиянию глобального состояния. Опять же, я не могу быть слишком конкретным, используя предоставленные образцы, но я думаю, что это должно проиллюстрировать концепции, которые я изначально обрисовал достаточно хорошо (я не думаю, что обзор всего проекта необходим).

0 голосов
/ 03 октября 2011

Для такого типа вещей мне нравится использовать NSNotifications. У вас есть все контроллеры представления, которые заботятся о положении стрелки, прослушивают определенное уведомление, и все они могут обновлять интерфейс сразу.

0 голосов
/ 03 октября 2011

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

Я стараюсь не злоупотреблять делегатом приложения так сильно, я создам синглтон для хранения более или менее глобальной информации.Нет другого способа сделать это, кроме как синглтона или делегата приложения.

Но если информация нужна только одному viewController, информация никогда не покинет этот viewController.Этот viewcontroller может передавать эту информацию другому viewcontroller.

В вашем случае может быть идея иметь какой-то вид directionManager, который содержит плавающие элементы и может даже содержать CLLocationManager.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...