【问题标题】:trouble setting NSWindow and UIView BackgroundColor in a loop within a method在方法内的循环中设置 NSWindow 和 UIView BackgroundColor 时遇到问题
【发布时间】:2012-05-18 03:44:50
【问题描述】:

在方法或循环中为 NSWindow (Mac OS X) 和 UIView (iOS) 设置背景颜色时遇到了很大的麻烦。 以下设置背景颜色的代码仅适用于循环中的最后一行代码,即当 i、j、k 的所有值均为 255 时,屏幕变为白色作为适当的 RGB 混合。

`- (void) ChangeColorLoop
{
for (int i=0; i<=255; i++)
    for (int j=0; j<=255; j++)
        for (int k=0; k<=255; k++)
        {
            [NSThread sleepForTimeInterval: 0.1];
            //NSLog(@"%d, %d, %d", i, j, k);
            float red = (float) i/255;
            float green = (float) j/255;
            float blue = (float) k/255;    
            float alpha = 1.0f;
            UIColor *mixedColor = [UIColor colorWithRed:red green:green blue:blue alpha:alpha];
            //BackgroundView.backgroundColor = mixedColor;
            [BackgroundView setBackgroundColor:mixedColor];
        }
}`

提前致谢,

杰瑞

【问题讨论】:

  • 此方法是否在后台线程上运行?
  • 我不知道,但它假设我发布的是 (IBAction) 而不是 (void)。所以当我点击按钮时,它会触发这个方法并开始运行。

标签: objective-c loops uiview background-color nswindow


【解决方案1】:

setBackgroundColor: 消息只有在您的代码返回事件循环时才会被执行,直到最后才会执行。这就是为什么只有最后一种颜色“需要”。

因此,您需要在后台线程上运行循环。 但是setBackgroundColor: 调用需要在主线程上(因为这是所有 UI 代码所在的位置)。

如果您使用 GCD,您的逻辑需要类似于:

-(void)changeColorLoop {
  dispatch_async(backgroundqueue, ^{
    for (;;) {
      // Do stuff
      dispatch_sync(main_queue, ^{
        [BackgroundView setBackgroundColor:mixedColor];
      });
    }
  });
}

【讨论】:

  • 它与另外两行代码一起工作,“dispatch_queue_t main_queue = dispatch_get_main_queue(); dispatch_queue_t backgroundqueue = dispatch_queue_create("com.app.request", NULL);"。太棒了,再次感谢!
【解决方案2】:

您的评论听起来像是在主线程上运行。我看到它有几个问题。您没有看到颜色变化的根本原因是您的循环阻塞了主线程,并且视图(通常)仅在运行循环周期结束时重绘。直到整个循环完成后才会发生这种情况。有多种方法可以解决这个问题。最简单的可能是每次通过 for 循环手动运行运行循环。您还可以将此工作移至后台线程并将setBackgroundColor: 调用分派到主队列。另一种方法是使用计时器(NSTimer 或计时器调度源)定期更新颜色。

在任何情况下,您都不应该在 for 循环中间休眠主线程。几乎没有充分的理由让主线程休眠,这样做会阻止您的 UI 更新或处理用户输入事件。

编辑:这里有一些示例代码显示了我提到的计时器方法:

@interface AppDelegate ()

@property (nonatomic, strong) NSTimer *colorChangeTimer;
@property (nonatomic) float red;
@property (nonatomic) float green;
@property (nonatomic) float blue;

@end

@implementation AppDelegate

- (id)init
{
    self = [super init];
    if (self) {
        self.red = 0.5;
        self.blue = 0.5;
        self.green = 0.5;
    }
    return self;
}

- (void)updateColors:(NSTimer *)timer
{
    NSColor *newColor = [NSColor colorWithDeviceRed:self.red green:self.green blue:self.blue alpha:1.0];
    [self.window setBackgroundColor:newColor];
    if (self.red >= 1.0) {
        [self.colorChangeTimer invalidate];
        self.colorChangeTimer = nil;
    }
    if (self.green > 1.0) {
        self.green = 0.0;
        self.red += 0.01;
    }
    if (self.blue >= 1.0) {
        self.blue = 0.0;
        self.green += 0.01;
    } else {
        self.blue += 0.01;
    }
}

- (IBAction)changeColors:(id)sender 
{
    if (self.colorChangeTimer != nil) return;
    self.colorChangeTimer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self selector:@selector(updateColors:) userInfo:nil repeats:YES];
}

@synthesize window = _window;
@synthesize colorChangeTimer = _colorChangeTimer;
@synthesize red = _red;
@synthesize green = _green;
@synthesize blue = _blue;

@end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-16
    • 2016-04-23
    • 2021-04-03
    • 1970-01-01
    相关资源
    最近更新 更多