2012-06-11 68 views
6

我已經看到了使用NSArray indexOfObjectPassingTest的幾個例子,但我無法讓它們工作(它們不會返回有效的索引)。 所以現在我試圖使用內聯塊。我通過typedef來創建一個塊,然後將其設置爲一個屬性,合成它並在構造函數中初始化它。然而,這種呈現整個點靜音,因爲我可以輕鬆地創建一個方法,並使用它(減少打字,減少工作量)。使用內聯塊搜索NSArray中的對象索引

我試圖做到的,是沿着這樣的:

Observations *obs = [self.myAppointment.OBSERVATIONS objectAtIndex: ^NSInteger (NSString *keyword){ 
    for (Observations *obs in self.myAppointment.OBSERVATIONS) { 
     if ([obs.TIME isEqualToString:keyword] == YES) return (NSInteger)[self.myAppointment.OBSERVATIONS indexOfObject:obs]; 
    } 
    return (NSInteger)-1; 
}]; 

然而Xcode中根本就沒有。我已經嘗試了不同的變化,但在宣佈它內聯似乎是一個問題,這是奇怪的,因爲正如我已經說過了,typedefing它,聲明,併合成它的工作原理是這樣的:

Observations *obs = [self.myAppointment.OBSERVATIONS objectAtIndex:findObs(keyword)]; 

哪裏findObs是再次是一個定義的塊,做同樣的事情。 這是一個語法問題,還是我錯過了其他更重要的東西?

回答

24

-objectAtIndex:NSUInteger作爲參數,但是您將它傳遞給一個塊(由^表示)。你的第二個例子調用findObs(可能是你的區塊)和keyword參數,將該調用的結果傳遞給-objectAtIndex:

你可能想結合-objectAtIndex:-indexOfObjectPassingTest:

NSString *keyword = /* whatever */; 
NSArray *array = self.myAppointment.OBSERVATIONS; 
NSUInteger idx = [array indexOfObjectPassingTest:^(id obj, NSUInteger idx, BOOL *stop){ 
    Observations *obs = (Observations*)obj; 
    return [obs.TIME isEqualToString:keyword]; 
}]; 
if (idx != NSNotFound) 
    Observations *obs = [array objectAtIndex:idx]; 
+0

感謝那些偉大的工作。所以,我認爲將一個內聯塊作爲一個NSInteger參數傳遞(實際上期望塊的返回值作爲參數傳遞)是不可行的,除非它的類型定義和合成? –

+0

你也可以在線調用你的塊:'[... objectAtIndex:(^ NSInteger(NSString * k){...})(keyword)];',但事情看起來有點混亂。 –

+1

該示例將返回數組中最後一個通過測試的對象。 只要找到第一個對象就停止迭代,您必須將'* stop'設置爲YES。 – Moose

3

這是沒有必要的typedef或合成任何事情,使你的第二個例子的工作 - 只是從一個方法,它看起來像這樣返回塊:

-(NSUInteger(^)(NSArray *, NSString *))findObs { 
    return ^(NSArray *array, NSString *keyword) { 
     for (NSUInteger i = 0; i < [array count]; i++) { 
      Observations *obs = [array objectAtIndex:i]; 
      if ([obs.TIME isEqualToString:keyword]) { 
       return i; 
      } 
     } 
     return NSNotFound; 
    }; 
} 

Observations *obs = [self.myAppointment.OBSERVATIONS objectAtIndex:[self findObs](keyword)]; 

這裏有一些good reasons for defining blocks as method return values, rather than inline

+1

您需要複製您要返回的區塊,除非您使用的ARC可以爲您做 – user102008

+1

是的,@ user102008,這是正確的。現在我通常會假設ARC,除非某人的代碼示例清楚他們沒有使用ARC。 –

4

這是一個返回字符串數組中字符串索引的示例。它可能適用於任何類型的對象。

NSString* myString = @"stringToFind"; 
NSUInteger objectIndex = [myStringArray indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) { 
     return (*stop = ([obj isEqualToString:myString])); 
    }]; 

要準確地回答原來的問題:

NSString *keyword = @"myKeyword"; 
NSUInteger index = [self.myAppointment.OBSERVATIONS indexOfObjectPassingTest:^(id obj, NSUInteger idx, BOOL *stop) { 
    return (*stop = [(Observations*)obs.TIME isEqualToString:keyword]); 
}]; 
Observations *obs = (index!=NSNotFound) ? self.myAppointment.OBSERVATIONS[index] : NULL; 

但是它是相當奇怪的東西比較調用時與關鍵字...;)