简单的NSTextList问题

时间:2011-08-23 16:05:56

标签: cocoa nstextfield

我正在尝试使用NSTextList在多行NSTextField中显示数字列表,但它无法按预期工作。

使用的示例代码是:

- (IBAction)displayResult:(id)sender
{
    NSTextList *list = [[NSTextList alloc] initWithMarkerFormat:self.markerFormat options:1]; // {Decimal} passed as marker format
    NSMutableParagraphStyle *paragraph = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
    [paragraph setTextLists:[NSArray arrayWithObject:list]];
    [list release];
    NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:paragraph, NSParagraphStyleAttributeName, nil];
    NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:self.inputString attributes:attributes] ; // input string is- George \n Thomas \n Ashok
    [self setOutputString:attrString]; 
    [attrString release];
    [paragraph release];
}

输入是 -

George 

Thomas 

Ashok

输出应为 -

1 George

2 Thomas

3 Ashok

但输出显示的是 -

George 

Thomas 

Ashok

有人能建议如何达到预期的产量吗?

2 个答案:

答案 0 :(得分:6)

你做的一切看起来都很好,对我来说是华丽的:)     输入字符串有问题     试试这个,

NSTextList *list1 = [[NSTextList alloc] initWithMarkerFormat:@"{decimal}" options:0]; // {Decimal} passed as marker format
NSMutableParagraphStyle *paragraph = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[list1 setStartingItemNumber:1];
[paragraph setTextLists:[NSArray arrayWithObject:list1]];

NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:paragraph, NSParagraphStyleAttributeName, nil];
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"\t%@ Suhas \n \t%@ Devarshi \n \t%@ Rohith\n", [list1 markerForItemNumber:1],[list1 markerForItemNumber:2],[list1 markerForItemNumber:3]] attributes:attributes] ;
 [self.text setStringValue:attrString];//self.text is a NSTextField instance. kindly ignore the compiler warning:)

答案 1 :(得分:2)

我知道这已经晚了四年,但我最近遇到了同样的问题并且能够使用Swift解决它。

我希望能够将NSTextView中的选定文本转换为项目符号列表,但选择显然可以跨越多个段落的部分。第一步是通过访问NSTextView.rangeForUserParagraphAttributeChange来确定正确的选择范围,这可以保证您始终选择包含完整段落的范围,而不是部分段落。

现在,更难的部分:您必须在修改的选择范围内找到每个段落并为其添加一个项目符号,以及添加正确的文本列表对象并替换修改后的选定范围中的文本以包含新的文本。这说起来容易做起来难,并花了几天时间才想出来(我还在上大学,所以去看看)。

我在互联网上几乎找不到任何关于此的内容,所以希望这将为未来的互联网旅行者带来麻烦。

if let range = textView?.rangeForUserParagraphAttributeChange {
// So, the user has selected some text. Range may or may not be the user's exact selection...
// The start of range has possibly back-tracked from the start of the selection to the start of
// the nearest paragraph, and the end has possibly extended from the end of the selection to the
// end of the nearest paragraph at that point.
// Therefore, we are guarunteed to be selecting complete paragraphs.
//
// Now, for each paragraph, we want to insert a bullet.
// The trick is finding the range of each paragraph.
//
// Find the attributed string contents of the entire possibly multi-paragraph selection:
let entireRangeText = textView!.textStorage!.attributedSubstringFromRange(range)
// Find the string contents
let entireRangeString = entireRangeText.string as NSString

// Let's make a list to store all of the paragraph ranges inside range
var paragraphRanges: [NSRange] = []

// Find the range of the first paragraph (possibly the only paragraph)
var paraRange = entireRangeString.paragraphRangeForRange(NSMakeRange(0, 0))
// Para range is relative to range, so let's keep track of it's actual position.
var actualRange = NSMakeRange(paraRange.location + range.location, paraRange.length)
// Add it to the list
paragraphRanges += [actualRange]

// Now find each paragraph inside the selection
while NSMaxRange(paraRange) < entireRangeString.length {
    // Find the next range relative to the range
    paraRange = entireRangeString.paragraphRangeForRange(NSMakeRange(NSMaxRange(paraRange), 0))
    // Find it's actual range relative to the entire text
    actualRange = NSMakeRange(paraRange.location + range.location, paraRange.length)
    // Add it to our list of paragraph ranges
    paragraphRanges += [actualRange]
}

// This is the attributed string that we will use to replace the entireRangeText
// with the bulleted version.
let newText = NSMutableAttributedString()

// Start counting our bullets at 1...
// Todo: Respect the starting number in the preferences
var bulletNumber = 1

// Make a list object to add to each paragraph
// Todo: Respect the list type specified
let list = NSTextList(markerFormat: "{decimal}", options: 0)

// Go through each paragraph range and add bullets to the text inside it
for paragraphRange in paragraphRanges {
    // Construct the bullet header:
    let bulletText = "\t" + list.markerForItemNumber(bulletNumber) + "\t"
    // Find the text from the paragraph
    let paragraphText = textView!.textStorage!.attributedSubstringFromRange(paragraphRange)
    let mutableParagraphText = NSMutableAttributedString(attributedString: paragraphText)

    // A range pointer we really don't need:
    var effectiveRange = NSRange()

    // Construct our new string appropriately
    // Get the paragraph attribute and modify it to have the text list
    if let paragraphStyle = paragraphText.attribute(NSParagraphStyleAttributeName,
                                                    atIndex: 0,
                                                    longestEffectiveRange: &effectiveRange,
                                                    inRange: NSMakeRange(0, paragraphText.length))
        as? NSParagraphStyle {
        let newParagraphStyle = paragraphStyle.mutableCopy() as! NSMutableParagraphStyle
        // Attach the list object to the paragraph style of the paragraph text
        // So that auto list continuation will work properly
        newParagraphStyle.textLists = [list]
        // Update the text's paragraph style:
        mutableParagraphText.addAttributes([NSParagraphStyleAttributeName: newParagraphStyle],
                                            range: NSMakeRange(0, paragraphText.length))
    }

    // Make the bullet's attributes match the attributes of the text it's near, just
    // like TextEdit does.
    newText.appendAttributedString(
        NSAttributedString(string: bulletText,
            attributes: mutableParagraphText.attributesAtIndex(0,
                longestEffectiveRange: &effectiveRange,
                inRange: NSMakeRange(0, paragraphText.length))))
    newText.appendAttributedString(mutableParagraphText)

    // Increase to the next bullet number:
    bulletNumber += 1
}

// Finally, insert our string
textView?.shouldChangeTextInRange(range, replacementString: nil)
textView?.insertText(newText, replacementRange: range)

// Tell the undo manager what happened:
textView?.didChangeText()
undoManager?.setActionName("Paragraph List") // ToDo: Localize

// Change the selection for auto-insertion to work
// IMPORTANT: Note that you have to change the selection twice to get auto list insertion to work
// (at least on my system). Must be a bug.
textView?.setSelectedRange(NSMakeRange(range.location + newText.string.characters.count - 1, 0))
textView?.setSelectedRange(NSMakeRange(range.location + newText.string.characters.count, 0))
}