0

我已向我的应用程序添加了用户选择的主题选项。每个相关元素(主要是 UIViews)根据 NSUserDefaults BOOL 的状态有条件地改变它们的外观。

当我使用#define 后跟Build and Run 设置状态时,这工作正常。但是,当用户拨动开关时,我需要 UI 来“刷新”。

从理论上讲,我认为我需要从 self.window 级联一个 setNeedsDisplay。有没有聪明的方法来实现这一点。我已经尝试在下面的链接中使用@mattmook 的解决方案来完成子视图,但它还不够远,我不确定这是实现我想要做的事情的最佳方式。

iPhone编程setNeedsDisplay不起作用

有人可以确认这是最好的方法还是建议更简单的方法?

谢谢,史蒂夫

4

3 回答 3

2

Make the interested views listen to a notification. When data change, send a notification and let all the views update themselves.

In general, it's better to have such functionality decentralized.

于 2013-06-14T17:46:13.260 回答
0

这取决于您实际应用颜色更改的方式。您是否对您使用的每个 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方法中。工作正常。我自己就是这么干的。

但是,对所有视图进行子类化可能会更有效,因为这意味着一次性工作,具体取决于应用程序的总大小。此外,它可以在其他应用程序中重复使用。

于 2013-06-14T18:01:24.823 回答
0

如果我要确保在每个单独的视图上点击 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;
}
于 2013-06-14T18:20:48.540 回答