2011-05-12 26 views
5

我在代碼中創建一個NSPredicateEditor並試圖實現我所希望的將是一項相當簡單的任務。基本上,我想顯示一個複合NSPredicateEditorRowTemplate(給予用戶在「All/Any /以下任何一個都不爲真」時執行匹配的選項)以及它下面的一些相當基本的子箭頭。爲此,我構建了NSPredicateEditor並綁定了它的值,以便在用戶編輯謂詞時保存更改。強制使用NSPredicateEditor顯示覆合行

我遇到的問題是,無論如何,默認情況下我無法將複合NSPredicateEditorRowTemplate顯示爲具有單個子行的父行。當我最初創建謂詞我通過一個假空謂詞,像這樣:

filename BEGINSWITH[cd] '' 

爲了強制化合物行我必須創建兩個子行的顯示:

filename BEGINSWITH[cd] '' && path ==[cd] '' 

作爲參考,這裏是我如何構建NSPredicateEditor:

NSArray *keyPaths = [NSArray arrayWithObjects:[NSExpression expressionForKeyPath:@"filename"], [NSExpression expressionForKeyPath:@"path"], nil]; 
NSArray *operators = [NSArray arrayWithObjects:[NSNumber numberWithInteger:NSEqualToPredicateOperatorType], 
                      [NSNumber numberWithInteger:NSNotEqualToPredicateOperatorType], 
                      [NSNumber numberWithInteger:NSBeginsWithPredicateOperatorType], 
                      [NSNumber numberWithInteger:NSEndsWithPredicateOperatorType], 
                      [NSNumber numberWithInteger:NSContainsPredicateOperatorType], 
                      nil]; 

NSPredicateEditorRowTemplate *template = [[NSPredicateEditorRowTemplate alloc] initWithLeftExpressions:keyPaths 
                      rightExpressionAttributeType:NSStringAttributeType 
                           modifier:NSDirectPredicateModifier 
                          operators:operators 
                           options:(NSCaseInsensitivePredicateOption | NSDiacriticInsensitivePredicateOption)]; 

NSArray *compoundTypes = [NSArray arrayWithObjects:[NSNumber numberWithInteger:NSNotPredicateType], 
                 [NSNumber numberWithInteger:NSAndPredicateType], 
                 [NSNumber numberWithInteger:NSOrPredicateType], 
                 nil]; 

NSPredicateEditorRowTemplate *compound = [[NSPredicateEditorRowTemplate alloc] initWithCompoundTypes:compoundTypes]; 
NSArray *rowTemplates = [NSArray arrayWithObjects:compound, template, nil]; 
[template release]; 
[compound release]; 

predicateEditor = [[NSPredicateEditor alloc] init]; 
[predicateEditor setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; 
[predicateEditor setRowTemplates:rowTemplates]; 
[predicateEditor setCanRemoveAllRows:NO]; 
[predicateEditor setContinuous:YES]; 
[predicateEditor setFrame:[[scrollView contentView] bounds]]; 

// Create a custom binding for our NSPredicateEditor 
SIPredicateStringValueTransformer *transformer = [[[SIPredicateStringValueTransformer alloc] init] autorelease]; 
NSMutableDictionary *bindingOptions = [NSMutableDictionary dictionaryWithObjectsAndKeys:transformer, NSValueTransformerBindingOption, [NSNumber numberWithBool:YES], NSValidatesImmediatelyBindingOption, nil]; 
[predicateEditor bind:@"value" toObject:self withKeyPath:@"self.filter.predicate" options:bindingOptions]; 

// Add our NSPredicateEditor to our NSScrollView 
[scrollView setDocumentView:predicateEditor]; 

回答

5

問題是你給它一個比較謂詞。你需要給它一個複合。

我猜你的SIPredicateStringValueTransformer對象正在接受一個字符串並將它變成一個謂詞,對嗎?而且它可能做這樣的事情:

- (id) transformedValue:(id)value { 
    return [NSPredicate predicateWithFormat:value]; 
} 

你想要做的,而不是什麼是保證該值轉換不只是返回任何舊的謂語,而是一個複合謂語(即NSCompoundPredicate代替NSComparisonPredicate)。做到這一點的方法很簡單:

- (id) transformedValue:(id)value { 
    NSPredicate *p = [NSPredicate predicateWithFormat:value]; 
    if ([p isKindOfClass:[NSComparisonPredicate class]]) { 
    p = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObject:p]]; 
    } 
    return p; 
} 

當你給一個NSCompoundPredicate謂詞編輯器,它顯示該化合物列。只給出比較謂詞時,它只顯示適當的比較行。

+1

這是完全正確的。謝謝你的詳細解答。希望這有助於未來的人。 – ndg 2011-05-14 22:16:11