2012-05-09 24 views
2

我很困難爲方法或循環內的NSWindow(Mac OS X)和UIView(iOS)設置背景顏色。 設置背景顏色的下列代碼僅適用於循環中代碼的最後一行,當i,j,k的所有值均爲255時,屏幕將變爲白色,以適合RGB混合。問題設置NSWindow和UIView BackgroundColor在一個方法內的循環

`- (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]; 
     } 
}` 

由於提前,

傑裏

+0

是在後臺線程運行的這種方法嗎? –

+0

我不知道,但它假設(IBAction),而不是(無效),因爲我張貼。所以當我點擊按鈕時,它會觸發這個方法,它會開始運行。 – Jerry

回答

0

setBackgroundColor:消息只會在你的代碼返回到事件循環,它不這樣做,直到要付諸行動最後。這就是爲什麼只有最後一種顏色「需要」。

所以,你需要在後臺線程上運行你的循環。 setBackgroundColor:調用需要在主線程(因爲這是所有的UI代碼去的地方)。

如果使用GCD,你的邏輯必須是這樣的:

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

它與另一個2行代碼, 「dispatch_queue_t main_queue = dispatch_get_main_queue(); dispatch_queue_t backgroundqueue = dispatch_queue_create(」 com.app.request 「NULL);」。太棒了,再次感謝! – Jerry

0

這聽起來這樣從你的評論是在主線程上運行。我看到它的幾個問題。你沒有看到顏色變化的根本原因是因爲你的循環阻塞了主線程,並且視圖(通常)只在運行循環結束時重繪。直到整個循環完成後纔會發生這種情況。有很多方法可以解決這個問題。最簡單的可能是每次通過for循環手動運行循環。您也可以將此工作移至後臺線程並將setBackgroundColor:調用分派給主隊列。另一種方法是使用定時器(NSTimer或定時器調度源)定期更新顏色。

在任何情況下,您都不應該在for循環中間休眠主線程。睡眠主線程幾乎沒有好的理由,這樣做會阻止您的用戶界面更新或處理用戶輸入事件。

編輯:這是表示該錄象的方法,我提到的一些示例代碼:

@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