2012-04-25 25 views
30

Trở lại một lần nữa cần trợ giúp thêm với xây dựng NSPredicates tôi :(Kết hợp 'AND' và 'OR' Điều kiện trong NSPredicate

Category 
{ 
    name:string 
    subs<-->>SubCategory 
} 

SubCategory 
{ 
    name:string 
    numbervalue:NSNumber 
} 

Tôi muốn biết làm thế nào để tạo ra một vị với HOẶC .

Ví dụ, tôi muốn trở về mỗi loại với tên == "CATEGORY_NAME" mà còn có một tiểu thể loại với một numbervalue của "valueA" HOẶC "VALUE tỷ".

Tôi đã thử mọi kết hợp có thể có của các hàm tạo vị ngữ mà tôi có thể đưa ra nhưng tôi không thể làm cho nó hoạt động được.

Đây là nỗ lực tốt nhất của tôi cho đến thời điểm này.

NSPredicate *predicate=[NSPredicate [email protected]"(name== %@) AND (ANY subs.numbervalue==%@ OR ANY subs.numbervalue==%@)", @"aname", value1, value2]; 

Sửa 1

nỗ lực thứ hai. Việc lọc trên 'numbervalue' vẫn không hoạt động.

NSNumber valueA=[NSNumber numberWithInt:20]; 
NSNumber valueA=[NSNumber numberWithInt:90]; 
NSArray *arr=[NSArray arrayWithObject:valueA,valueB,nil]; 

predicate=[NSPredicate predicateWithFormat:@"(name==%@)AND(ANY subs.numbervalue IN %@)",@"aname",arr]; 

Chỉnh sửa 2

tôi đã cố gắng lọc chỉ bằng cách numberValue và đã để lại tên ra alltogether.

1) sử dụng kết quả này trong toàn bộ tập hợp được trả lại ngay cả khi chỉ 1 mục trong tập hợp có giá trị.

predicate=[NSPredicate predicateWithFormat:@"(ANY subs.numbervalue IN %@)",arr]; 

2) Sử dụng kết quả này trong cùng một vấn đề, mọi mục trong tập hợp sẽ được trả về ngay cả khi chỉ 1 mục phù hợp.

predicate=[NSPredicate predicateWithFormat:@"((SUBQUERY(subs, $x, $x.numbervalue == %@ or $x.numbervalue == %@)[email protected] > 0)", value1, value2]; 

Cũng sử dụng phiên bản đơn giản nhất dẫn đến cùng một vấn đề .... Tôi không nhận thấy điều này trước đó.

NSPredicate *predicate=[NSPredicate [email protected]"(ANY subs.numbervalue==%@ ,valueA]; 

Vì vậy, tôi nghĩ rằng vấn đề của tôi đã bị thu hẹp.

Danh mục là một Thực thể. Danh mục con là một Thực thể.

Danh mục có mối quan hệ một đến nhiều với Danh mục phụ và được biểu diễn dưới dạng NSSet của Danh mục phụ.

Mỗi Danh mục con có một thuộc tính có tên là numbervalue.

Sửa 3

Để kiểm tra tôi có 2 chuyên cung. Cả hai Danh mục đều có 10 người đăng ký, mỗi danh mục có một sự sụt giảm 1 -10;

Sử dụng mã này cả hai danh mục đều được trả về cùng với tất cả 10 người đăng ký cho mỗi danh mục.

Kết quả mong đợi là cả hai danh mục được trả lại, mỗi danh mục chỉ có 2 người đăng ký.

Tôi đã theo dõi tất cả các đối tượng của tôi và dữ liệu là chính xác. Vấn đề là tôi không thể trả lại một thể loại đã lọc subs.

NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; 
NSManagedObjectContext *context=[[DataSource sharedDataSource]managedObjectContext]; 
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Category" inManagedObjectContext:context]; 
[fetchRequest setEntity:entity]; 

[fetchRequest setFetchBatchSize:20]; 

NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES]; 
NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil]; 

NSPredicate *predicate; 
NSNumber *a=[NSNumber numberWithFloat:1]; 
NSNumber *b=[NSNumber numberWithFloat:2]; 
predicate=[NSPredicate predicateWithFormat:@"(SUBQUERY(subs,$x,$x.numbervalue==%@ or $x.numbervalue==%@)[email protected]> 0)",a,b]; 

[fetchRequest setPredicate:predicate]; 
[fetchRequest setSortDescriptors:sortDescriptors]; 

NSError *error = nil; 
[NSFetchedResultsContoller deleteCacheWithName:nil]; 

NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:@"name" cacheName:@"Master"]; 
aFetchedResultsController.delegate = self; 

self.fetchedResultsController = aFetchedResultsController; 

if (![self.fetchedResultsController performFetch:&error]) { 

    NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
    abort(); 
} 
+0

Bạn đã kiểm tra 'NSCompoundPredicate'? Nó sẽ giúp bạn. Ngoài ra, hãy thử sử dụng '... AND (ANY subs.numberValue IN% @)", @ "fooName", numArray' – Eimantas

+0

cảm ơn các mẹo – dubbeat

+0

sử dụng $ x.numbervalue chứ không phải $ numbervalue. Sau đó thử đặt bộ nhớ cache thành nil đầu tiên và xem kết quả –

Trả lời

32

Tôi sẽ làm như sau bằng cách sử dụng SUBQUERY.

[NSPredicate [email protected]"(name == %@) AND (SUBQUERY(subs, $x, $x.numbervalue == %@ or $x.numbervalue == %@)[email protected] > 0)", @"aname", value1, value2]; 

Hãy thử và cho tôi biết.

Một giải pháp khác có thể là lấy toàn bộ bộ sưu tập subs và sau đó lọc bộ đã truy xuất bằng vị từ để kiểm tra xem các phần tử có khớp với value1 hoặc value2 hay không.

Hy vọng điều đó sẽ hữu ích.

Sửa

Nếu bạn làm theo Eimantas đề nghị làm cho chắc chắn để tạo ra các mảng phải:

NSNumber valueA = [NSNumber numberWithInt:20]; 
NSNumber valueB = [NSNumber numberWithInt:90]; 
NSArray *arr = [NSArray arrayWithObjects:valueA, valueB, nil]; 
+0

những gì dường như đang xảy ra là nếu một bộ sưu tập của subs có một số giá trị là 90 ví dụ, nhưng phần còn lại là 0, toàn bộ bộ sưu tập của subs vẫn được returnd – dubbeat

+0

Hãy thử sử dụng chỉ * (SUBQUERY (subs, $ x, $ x.numbervalue ==% @ hoặc $ x.numbervalue ==% @). @ count> 0) * trong vị từ và lọc mảng với một vị từ bổ sung để tìm Tên. –

+0

Bạn lấy kết quả gì khi chỉ sử dụng SUBQUERY? –

49

Ngoài câu trả lời của @ Stuart, bạn có thể sử dụng NSCompoundPredicate cho HOẶC & VÀ các hoạt động như thế này.

obj-C - HOẶC

// OR Condition // 

NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"X == 1"]; 
NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"X == 2"]; 
NSPredicate *predicate = [NSCompoundPredicate orPredicateWithSubpredicates:@[predicate1, predicate2]]; 

obj-C - VÀ

NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"X == 1"]; 
NSPredicate *predicate2 = [NSPredicate predicateWithFormat:@"X == 2"]; 
NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[predicate1, predicate2]]; 

Swift - HOẶC

let predicate1:NSPredicate = NSPredicate(format: "X == 1") 
let predicate2:NSPredicate = NSPredicate(format: "Y == 2") 
let predicate:NSPredicate = NSCompoundPredicate(orPredicateWithSubpredicates: [predicate1,predicate2]) 

Swift - VÀ

let predicate1:NSPredicate = NSPredicate(format: "X == 1") 
let predicate2:NSPredicate = NSPredicate(format: "Y == 2") 
let predicate:NSPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: [predicate1,predicate2]) 

Swift 3 - HOẶC

let predicate1 = NSPredicate(format: "X == 1") 
    let predicate2 = NSPredicate(format: "Y == 2") 
    let predicateCompound = NSCompoundPredicate.init(type: .or, subpredicates: [predicate1,predicate2]) 

Swift 3 - VÀ

let predicate1 = NSPredicate(format: "X == 1") 
    let predicate2 = NSPredicate(format: "Y == 2") 
    let predicateCompound = NSCompoundPredicate.init(type: .and, subpredicates: [predicate1,predicate2]) 
+0

Yêu thích nó! Mã của tôi trông đẹp hơn như thế này –

+0

Mã đẹp ... làm việc cho tôi. Upvoted !!! – NSPratik

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