简单的 NSTextList 问题

问题描述 投票:0回答:2

我正在尝试使用

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

谁能建议如何实现预期的输出?

cocoa nstextfield
2个回答
7
投票

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

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:)

4
投票

我知道这已经晚了四年了,但我最近遇到了同样的问题,并且能够使用 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))
    // paraRange 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))
}
© www.soinside.com 2019 - 2024. All rights reserved.