2010-03-31 28 views
23

Có cách nào xây dựng một vị từ để lọc theo loại lớp không?Có thể lọc NSArray theo lớp không?

Tôi hiện đang lặp qua mảng và kiểm tra lớp của từng đối tượng. Có lẽ có một cách sạch hơn?

+0

Tại sao bạn đặt các đối tượng khác nhau vào cùng một mảng ở địa điểm đầu tiên? –

+12

Một lý do là nếu bạn có một loạt các lớp trừu tượng. Bạn có thể có tất cả các lớp Person, nhưng bạn muốn lọc ra các bác sĩ hoặc luật sư. – rob5408

Trả lời

22

Bạn có thể thêm một loại để NSObject có thêm một phương pháp "cf_className", như vậy:

@interface NSObject (CFAdditions) 
- (NSString *) cf_className; 
@end 

@implementation NSObject (CFAdditions) 
- (NSString *) cf_className { 
    return NSStringFromClass([self class]); 
} 
@end 

Từ đó, bạn có thể sử dụng các vị từ như:

NSPredicate * p = [NSPredicate predicateWithFormat:@"cf_className = %@", aClass]; 
NSArray * filtered = [anArray filteredArrayUsingPredicate:p]; 

Nếu bạn đang ở trên máy Mac, bạn chỉ có thể sử dụng -[NSObject className] thay vì phải tạo danh mục. IPhone không có phương pháp đó, do đó sự cần thiết cho một thể loại.

+8

Bạn cũng có thể tự chụp.class.description –

+0

@BrianKing điểm tuyệt vời –

70

Bạn có thể so sánh trực tiếp các lớp cũng như trong vị từ của bạn.

Nhưng, nó có thể sẽ không hoạt động như bạn mong đợi nếu bạn đang cố gắng lọc cho các đối tượng thuộc về nhóm lớp hoặc nếu bạn có lớp con.

Ví dụ: NSDate khi được khởi tạo thường là __NSCFDateNSString có thể là NSCFString cũng như các lớp riêng tư cụ thể khác.

Có thể tốt hơn là chỉ lặp lại thiết lập cho mình và sử dụng -isKindOfClass: làm thử nghiệm.

NẾU bạn thực sự muốn sử dụng NSPredicate mặc dù bạn có thể thực hiện việc này. Ví dụ, điều này sẽ lọc một mảng cho tất cả các đối tượng bắt nguồn từ NSString. Nếu bạn muốn thành viên lớp học nghiêm ngặt, bạn có thể thay thế isKindOfClass: bằng isMemberOfClass:.

Bất kỳ bộ chọn nào mà tất cả các đối tượng trong bộ sưu tập đang triển khai, cần một đối số và trả về BOOL sẽ hoạt động.

NSArray *mixedArray = {...}; 
NSPredicate *predicate = [NSPredicate predicateWithFormat: 
             @"self isKindOfClass: %@", 
             [NSString class]]; 

NSLog(@"%@", [mixedArray filteredArrayUsingPredicate:predicate]); 
+1

+1 Tôi chưa bao giờ nghĩ đến việc đặt bộ chọn trực tiếp vào vị từ. Khéo léo! –

+1

Nó không được đề cập trong Hướng dẫn lập trình dành riêng (có nghĩa là làm điều này trong một chuỗi định dạng là không có giấy tờ về mặt kỹ thuật), nhưng tính năng tùy chỉnh-selector được sao lưu bằng tham chiếu: http://developer.apple.com/mac/library/ tài liệu/Cocoa/Tham khảo/Nền tảng/Lớp học/NSComparisonPredicate_Class/Tham khảo/NSComparisonPredicate.html # // apple_ref/occ/clm/NSComparisonPredicate/predicateWithLeftExpression: rightExpression: customSelector: Rất hay. –

+0

Vâng, ban đầu tôi đã viết nó rất lâu nhưng trên một lark đã thử nó trong chuỗi định dạng và ngạc nhiên khi thấy nó hoạt động. –

22

Bắt đầu từ iOS 4 và Mac OS 10.6, người ta cũng có thể sử dụng +[NSPredicate predicateWithBlock:]. Ví dụ:

NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) { 
    return [object isKindOfClass:[NSString class]]; 
}]; 

Điều này cho phép bạn thể hiện các biến vị ngữ hoàn toàn trong Mục tiêu-C thay vì cú pháp vị ngữ được yêu cầu bởi predicateWithFormat:.

+4

ứng dụng này xứng đáng có nhiều phiếu bầu hơn –

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