Темы, выбранные пользователем в iOS. Возможен ли setNeedsDisplay для всего пользовательского интерфейса?

Я добавил выбранную пользователем тему в свое приложение. Каждый соответствующий элемент (в основном UIViews) условно меняет свой внешний вид в зависимости от состояния NSUserDefaults BOOL.

Это работало нормально, когда я устанавливал состояние с помощью #define, за которым следовал Build and Run. Но мне нужно, чтобы пользовательский интерфейс «обновлялся», когда пользователь переключает переключатель.

Теоретически я думаю мне нужно каскадировать setNeedsDisplay вниз от self.window. Есть ли умный способ добиться этого. Я пытался работать с subViews, используя решение @mattmook по ссылке ниже, но этого недостаточно, и я не уверен, что это лучший способ добиться того, что я пытаюсь сделать.

Программирование iPhone setNeedsDisplay не работает

Может ли кто-нибудь подтвердить, что это лучший метод, или предложить что-то более простое?

Спасибо, Стив


person Steve    schedule 14.06.2013    source источник


Ответы (3)


Заставьте заинтересованные взгляды слушать уведомление. Когда данные изменяются, отправьте уведомление и позвольте всем представлениям обновиться.

В общем, лучше, чтобы такой функционал был децентрализован.

person Sulthan    schedule 14.06.2013
comment
Я согласен. Вы, вероятно, потратите слишком много времени на перебор UIViews, которые не нужно менять, если попытаетесь перемещаться по всей иерархии представлений. Это проблема, которую NSNotification призван решить. - person Aaron Brager; 14.06.2013

Это зависит от того, как вы на самом деле применяете изменение цвета. Вы подклассировали каждый объект UIView, который вы используете, чтобы гарантировать, что он извлекает свой цвет откуда угодно и соответствующим образом изменяет его, прежде чем рисовать себя? Например, перезапись drawRect следующим образом:

- (void) drawRect:... {

  if (somehowFetchTheUserDefaultsBoolValueHere) {
    self.tint = [UIColor redColor];  // details here may vary depedning on the actual superclass
  } else {
    self.tint = [UIColor greenColor];
  }

  [super drawRect:...];
}

(Просто показываю принцип. На самом деле есть более умные способы кодирования.)

Если бы вы сделали это, то setNeedsDisplay на текущем контроллере представления self.view подойдет. (в основной теме, если сомневаетесь)

Альтернатива: если вы выполняете тонирование любым другим способом, вам нужно выполнить тот код, который подкрашивает все представленные в данный момент представления. В большинстве случаев это контроллер представления сверху. Для всех других контроллеров представления вы можете поместить код окрашивания в их метод viewWillAppear. Работает отлично. Сделал это сам недавно.

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

person Hermann Klecker    schedule 14.06.2013

Если бы я собирался убедиться, что нажимаю setNeedsDisplay в каждом отдельном представлении (или вызываю метод с общим именем, такой как drawRect, или любой другой пользовательский метод, такой как представление обновления), я бы сделал это рекурсивно.

-(UIView *)redrawView:(UIView *)theView
{
    if([[theView subviews] count] = 0)
    {
        [self setNeedsDisplay];
        return theView;
    }

    for(UIView *subview in theView.subviews)
    {
        UIView *result = [self redrawView:subview];
        if(result) return result;
    }
    return nil;
}
person Chip Snyder    schedule 14.06.2013