2012-06-11 28 views
6

Tôi đã nhìn thấy một vài ví dụ xung quanh bằng cách sử dụng NSArray indexOfObjectPassingTest, nhưng tôi không thể làm cho chúng hoạt động (chúng sẽ không trả về một chỉ mục hợp lệ). Vì vậy, bây giờ tôi đang cố gắng sử dụng một khối nội tuyến. Tôi đã thực hiện nó bằng cách gõ một khối, sau đó thiết lập nó như là một thuộc tính, tổng hợp nó, và khởi tạo nó trong constructor. Tuy nhiên, loại đó làm cho toàn bộ điểm bị tắt tiếng, vì tôi có thể dễ dàng tạo ra một phương thức và sử dụng nó thay thế (ít đánh máy hơn, ít nỗ lực hơn).Tìm kiếm một chỉ mục đối tượng trong NSArray bằng cách sử dụng một khối nội tuyến

Những gì tôi đang cố gắng để đạt được là cái gì đó dọc này:

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

Tuy nhiên Xcode chỉ đơn giản là sẽ không có nó. Tôi đã cố gắng biến thể khác nhau, nhưng tuyên bố nó inline có vẻ là một vấn đề, đó là lạ, bởi vì như tôi đã nói, nó typedefing, tuyên bố, và tổng hợp nó hoạt động như thế này:

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

đâu findObs là một lần nữa một khối được xác định làm điều tương tự. Đây có phải là vấn đề về cú pháp hay không, tôi có thiếu cái gì khác quan trọng hơn không?

Trả lời

24

-objectAtIndex: mất một tham số NSUInteger, nhưng bạn chuyển nó qua một khối (ký hiệu là ^). Ví dụ thứ hai của bạn gọi số findObs (có thể là khối của bạn) với đối số keyword, chuyển qua kết quả của cuộc gọi đó đến -objectAtIndex:.

Có thể bạn muốn kết hợp -objectAtIndex: với -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

Cảm ơn mà làm việc tuyệt vời. Vì vậy, tôi lấy nó mà đi qua một khối nội tuyến như một tham số NSInteger (về cơ bản hy vọng giá trị trả về của khối được thông qua như tham số) là không thể làm được, trừ khi loại của nó được xác định và tổng hợp? –

+0

Bạn cũng có thể gọi khối nội tuyến của bạn: '[... objectAtIndex: (^ NSInteger (NSString * k) {...}) (từ khoá)];', nhưng mọi thứ bắt đầu hơi lộn xộn một chút. –

+1

Ví dụ này sẽ trả về đối tượng cuối cùng vượt qua thử nghiệm trong mảng. Để dừng lặp lại ngay khi tìm thấy đối tượng đầu tiên, bạn phải đặt '* stop' thành' YES' – Moose

3

Đó không phải là cần thiết để typedef hoặc tổng hợp bất cứ điều gì để làm cho công việc ví dụ thứ hai của bạn - chỉ cần trả lại khối từ một phương pháp, trong đó sẽ trông như thế này:

-(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)]; 

Dưới đây là một số good reasons for defining blocks as method return values, rather than inline.

+1

bạn cần phải sao chép khối bạn đang quay trở lại, trừ khi bạn đang sử dụng ARC, điều đó cho bạn – user102008

+1

Có, @ user102008, điều đó là chính xác. Tôi thường giả sử ARC những ngày này, trừ khi nó rõ ràng từ mẫu mã của ai đó mà họ không sử dụng ARC. –

4

Đây là ví dụ trả về chỉ mục của một chuỗi trong một chuỗi các chuỗi. Nó có thể thích nghi với bất kỳ loại đối tượng nào.

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

Để trả lời câu hỏi ban đầu một cách chính xác:

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; 

Nhưng nó khá lạ để so sánh một cái gì đó gọi là thời gian với một từ khóa ...;)

Các vấn đề liên quan