2012-05-23 47 views
2

如果我想要做的事情是可能的,我不知道。我對塊沒有經驗,只是閱讀了一些教程,非常喜歡這個想法。 我的類AppointmentView.h(和m)擴展了ViewController。它包含一些屬性,這些屬性是另一個類別約會的成員,而這些屬性又有一些NSArrays。 爲了創建分組tableview,我檢查數組的值,然後適當複製將顯示的值(沒有太花哨或複雜)。 通常我會去的if-else語句,並適當地控制,望着塊後,但是,它讓我想,如果以下是可行的:用動態代碼枚舉NSArray的Block-Closures和三元運算符

[self setOutcomes: [[NSArray alloc] initWithObjects: 
         ^{ return [myAppointment.CANCELED isEqualToString:@"NO"] == YES ? 
                  [[NSString alloc] initWithString:@"Not Cancelled"] : 
                  [[NSString alloc] initWithString:@"Cancelled"]; }, 
         ^{ return [myAppointment.CANCELED isEqualToString:@"NO"] == YES ? 
                  [[NSString alloc] initWithString:@"No Cancellation reason"] : 
                  [[NSString alloc] initWithString:myAppointment.CANCREASON]; }, 
         ^{ return [myAppointment EVENTS].length > 0 ? 
                  [[NSString alloc] initWithString:myAppointment.EVENTS] : 
                  [[NSString alloc] initWithString:@"No Events"]; }, 
         ^{ return [myAppointment SUMMARY].length > 0 ? 
          [[NSString alloc] initWithString:myAppointment.SUMMARY] : 
          [[NSString alloc] initWithString:@"No Summary"]; }, 
         nil]]; 

此代碼編譯罰款,但它崩潰運行時。我的理解是這是錯誤的,因爲我每次都要讓枚舉執行一段代碼。所以這不是我想要的。 後來我試過如下:

[self setOutcomes: [[NSArray alloc] initWithObjects: 
         [[NSString alloc] initWithString: (NSString *) ^(void){ 
                     return [myAppointment.CANCELED isEqualToString:@"NO"] == YES ? 
                             @"Not Cancelled" : @"Cancelled"; }], 
         [[NSString alloc] initWithString: (NSString *) ^(void){ 
                     return [myAppointment.CANCELED isEqualToString:@"NO"] == YES ? 
                             @"No Cancellation reason" : myAppointment.CANCREASON; }], 
         [[NSString alloc] initWithString: (NSString *) ^(void){ 
                     return [myAppointment.EVENTS isEqualToString:@""] == YES ? 
                             myAppointment.EVENTS : @"No Events"; }], 
         [[NSString alloc] initWithString: (NSString *) ^(void){ 
                     return [myAppointment.SUMMARY isEqualToString:@""] == YES ? 
                             myAppointment.SUMMARY : @"No Summary"; }], 
         nil]]; 

這雖然它編譯罰款,並出現以下錯誤崩潰:

-[NSMallocBlock length]: unrecognized selector sent to instance 0x6bd68f0

我也試過typedefining,我可以用一個通用的方法,但沒有幫助的。 所以,我想知道,這可能嗎?我知道,對於這段代碼,我可以簡單地使用if-else(就像我通常會這樣做)並完成它,但是其他情況下,這種動態代碼生成選項將非常有用。

我的感覺是,無論是NSString的不知道如何處理這一點,因此我應該有一個選項擴展它讓說

initWithBlock:

還是我人在這裏失去了一些東西。或者它可能只是不可能....(?)

PS:我剛剛看到NSArray的enumerateUsingBlock:方法,但我不確定這是否會在這種情況下,我的目的,因爲數組中的每個條目是完全不同的,而一個特定的塊不符合標準。

回答

3

如果您需要在初始化程序中進行簡單的選擇,則不需要塊。

[NSArray initWithObjects: 
     ([myAppointment.CANCELED isEqualToString:@"NO"] ? @"Not Cancelled" : @"Cancelled"), 
     ([myAppointment.CANCELED isEqualToString:@"NO"] ? @"No Cancellation reason" : myAppointment.CANCREASON), 
     nil]; 

使用parens來包圍?:運算符。


更新來回答如何在同一地點定義和調用塊問題

這個單元測試工作對我來說:

- (void)testBlockNow 
{ 
    BOOL X = ^{ return YES; }(); 
    STAssertTrue(X, nil); 
} 

這很簡單:^{ … }定義塊,然後()來調用該塊。

+0

謝謝,這工作得很好。在這種情況下,這就足夠了。然而,在更復雜的情況下,如果三元運算符不夠用,我怎麼能使用當場定義的塊而不是三元運算符? –

+0

爲我更新了我的答案。 –

+1

@Alex:有一個GCC擴展,它可以讓你將一個任意複雜的語句塊作爲一個表達式來包含:gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html我認爲這樣可以做到你想要的而不會搞亂當你不需要它時,用塊。 – newacct

2

是的,你可以將塊存儲在一個數組中,但你需要對它有所瞭解。

typedef (void)(^X)(); 

X block1 = ^{ … }; 
X block2 = ^{ … }; 
X block3 = ^{ … }; 

NSArray *array = [NSArray initWithObjects: 
        [[block1 copy] autorelease], 
        [[block2 copy] autorelease], 
        [[block3 copy] autorelease], 
        nil]; 
+0

這是非常有用的,但不是真正的我以後,因爲在這種情況下,你正在使用不同的塊爲每個案件。我寧願不定義任何東西,但隨着值的填充,實現該塊。 –

+0

我不確定你要求什麼。如果你想動態添加和刪除數組中的塊,這是可能的。使用帶有-addObject:和-removeObject:的NSMutableArray。如果你想在運行時創建新塊,這在編譯語言中是不可能的。 –

+0

不完全是,我希望編譯的代碼(塊)根據其他變量動態生成字符串的值。我可能會做錯誤的參數和指針,因爲我得到的錯誤似乎表明沒有選擇器爲某些實例設置。現在就試試你的例子。 –