2016-07-29 66 views
3

我想要一個包含純文本和標記的NSTokenField。這與this question中的問題是一樣的,但那裏的答案還沒有爲我解決。也許我錯過了一些東西,或者蘋果公司在發佈這些答案後的5年中改變了一些東西。在NSTokenField中混合標記和字符串

具體來說,假設我要輸入「你好%TOK%」,並把它變成這樣:

image of text "hello" and token "TOKEN"

爲了嘗試刪除混亂的機會,我總是使用代表自定義對象,下面的類,而不是一個普通字符串之一...

@interface Token : NSObject 
@end 

@implementation Token 
@end 


@interface WrappedString : NSObject 
@property (retain) NSString* text; 
@end 

@implementation WrappedString 
@end 

這裏是我的委託方法:

- (NSString *)tokenField:(NSTokenField *)tokenField 
    displayStringForRepresentedObject:(id)representedObject 
{ 
    NSString * displayString = nil; 
    if ([representedObject isKindOfClass: [WrappedString class]]) 
    { 
     displayString = ((WrappedString*)representedObject).text; 
    } 
    else 
    { 
     displayString = @"TOKEN"; 
    } 
    return displayString; 
} 

- (NSTokenStyle)tokenField:(NSTokenField *)tokenField 
       styleForRepresentedObject:(id)representedObject 
{ 
    NSTokenStyle theStyle = NSPlainTextTokenStyle; 
    if ([representedObject isKindOfClass: [Token class]]) 
    { 
     theStyle = NSRoundedTokenStyle; 
    } 

    return theStyle; 
} 

- (NSString *)tokenField:(NSTokenField *)tokenField 
     editingStringForRepresentedObject:(id)representedObject 
{ 
    NSString * editingString = representedObject; 
    if ([representedObject isKindOfClass: [Token class]]) 
    { 
     editingString = nil; 
    } 
    else 
    { 
     editingString = ((WrappedString*)representedObject).text; 
    } 
    return editingString; 
} 

- (id)tokenField:(NSTokenField *)tokenField 
    representedObjectForEditingString:(NSString *)editingString 
{ 
    id repOb = nil; 
    if ([editingString isEqualToString:@"tok"]) 
    { 
     repOb = [[[Token alloc] init] autorelease]; 
    } 
    else 
    { 
     WrappedString* wrapped = [[[WrappedString alloc] 
      init] autorelease]; 
     wrapped.text = editingString; 
     repOb = wrapped; 
    } 
    return repOb; 
} 

當我輸入「hello」時,沒有一個委託方法被調用,這似乎是合理的。當我鍵入第一個「%」,有3個代表電話:

  1. tokenField:representedObjectForEditingString:得到字符串「hello」,並把它變成一個WrappedString表示。
  2. tokenField:styleForRepresentedObject:得到WrappedString並返回NSPlainTextTokenStyle
  3. tokenField:editingStringForRepresentedObject:獲取WrappedString並返回「hello」。

前兩個調用似乎是合理的。我不確定3號,因爲令牌應該是可編輯的,但它尚未被編輯。我會認爲tokenField:displayStringForRepresentedObject:會被調用,但它不會。

當我輸入「tok」時,沒有委託方法被調用。當我輸入第二個「%」時,tokenField:representedObjectForEditingString:收到字符串「hellotok」,我希望看到的只是「tok」。所以我從來沒有機會創建圓形標記。

如果我按照其他順序「%tok%hello」鍵入文本,那麼我會得到預期的結果,一個圓形標記,後面跟一個普通的「hello」。

順便說一句,在Token Field Programming Guide

注意,可以有每個被配置爲純文本標記風格令牌場只有一個令牌。

這似乎暗示它不可能自由混合純文本和標記。

+0

我認爲蘋果改變了一些東西,NSPlainTextTokenStyle不再工作。我不知道它是一個錯誤還是一個功能。舊的(2015)示例代碼使用NSPlainTextTokenStyle,但它具有相同的問題,我無法再下載該示例。 – Willeke

回答

1

我問自己我是否曾在標準應用程序的任何地方見過混合的文本和標記,而且我曾經見過。在系統預置語言文字&面板,則格式選項卡下,點擊「自定義...」按鈕之一帶來了包含代碼字段的對話框。這是一個部分。

enter image description here

在這裏,你不通過鍵入一個符號化人物創建令牌,你拖放原型令牌。

要製作其中一個原型令牌,請創建另一個NSTokenField並將其設置爲沒有背景或邊框,並且可以選擇但不可編輯。當你的窗口已經加載,可以使用objectValue屬性,例如初始化原型場,

self.protoToken.objectValue = @[[[[Token alloc] init] autorelease]]; 

您需要設置爲每個原型標記領域的代表,以及您可編輯標記字段。爲了能夠拖放令牌,您的代理必須實施tokenField:writeRepresentedObjects:toPasteboard:tokenField:readFromPasteboard: