3

これが私の状況です:

NSMutableAttributedStringテキスト ビューに属性のない があります。ユーザーがバックスペース キーを押すたびに、生産性スイートの「変更の追跡」機能と同じように、文字を削除したくありません。その後、ユーザーが通常どおり入力を続けられるようにしたい。これが私が始めた方法です:

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
if (text.length == 0 && textView.text.length == 0) return YES;

if (text.length == 0 && !([[textView.text substringFromIndex:textView.text.length - 1] isEqualToString:@" "] || [[textView.text substringFromIndex:textView.text.length - 1] isEqualToString:@"\n"])) {

    textView.attributedText = [self strikeText:textView.attributedText];

    textView.selectedRange = NSMakeRange(textView.attributedText.length - 1, 0);

    return NO;
}
return YES;
}

- (NSAttributedString *)strikeText:(NSAttributedString *)text
{
NSRange range;
NSMutableAttributedString *returnValue = [[NSMutableAttributedString alloc] initWithAttributedString:text];

if (![text attribute:NSStrikethroughStyleAttributeName atIndex:text.length - 1 effectiveRange:&range]) {
    NSLog(@"%@", NSStringFromRange(range));
    NSLog(@"%@", [text attribute:NSStrikethroughStyleAttributeName atIndex:text.length - 1 effectiveRange:&range]);

    [returnValue addAttribute:NSStrikethroughStyleAttributeName value:@(NSUnderlineStyleSingle) range:NSMakeRange(text.length - 1, 1)];
    [returnValue addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(text.length - 1, 1)];
}
else {
    [returnValue addAttribute:NSStrikethroughStyleAttributeName value:@(NSUnderlineStyleSingle) range:NSMakeRange(range.location - 1, 1)];
    [returnValue addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(range.location - 1, 1)];
}

[returnValue removeAttribute:NSStrikethroughStyleAttributeName range:NSMakeRange(returnValue.length, 1)];

return returnValue;


}

しかし、いくら考えても状況が頭に浮かびません。このコードは機能しないか、部分的に機能します。によって返される値attribute: atIndex: effectiveRange:は常に nil であり、属性が実際に存在するかどうかは関係ありません。有効範囲は、私が持っているテキストの範囲外です。

ここで私を助けてください。

4

2 に答える 2

6

strikeText:メソッドでは、attributedString の最後だけをチェックしています。最後の文字を確認したい場合はtext.length -2、テキストが十分に長いと仮定して、から確認する必要があります。また、メソッドの最後にある removeAttribute もあまり意味がありません。

Delegate-Protocol の範囲を再利用して、必要な文字のみを攻撃する方法に関する簡単なアプローチ:

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
    // check if your replacement is going to be empty, therefor deleting
    if ([text length] == 0) {

        // don't strike spaces and newlines, could use NSCharacterSet here
        NSString *textToDelete = [textView.text substringWithRange:range];
        if (![@[ @" ", @"\n" ] containsObject:textToDelete]) {
            textView.attributedText = [self textByStrikingText:textView.attributedText inRange:range];
        }

        textView.selectedRange = NSMakeRange(range.location, 0);

        return NO;
    }

    return YES;
}

- (NSAttributedString *)textByStrikingText:(NSAttributedString *)text inRange:(NSRange)range
{    
    NSMutableAttributedString *strickenText = [[NSMutableAttributedString alloc] initWithAttributedString:text];

    [strickenText addAttribute:NSStrikethroughStyleAttributeName value:@(NSUnderlineStyleSingle) range:range];
    [strickenText addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:range];

    return strickenText;
}

より多くのエッジケースがあるかもしれませんが、これはあなたが望むことをする単純なアプローチです.

于 2013-06-23T10:25:26.943 に答える
5

試してみてください:

NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:@"Hello. That is a test"];
[str addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:22] range:NSMakeRange(2,1)];
[str addAttribute:NSForegroundColorAttributeName value:[UIColor greenColor] range:NSMakeRange(8,2)];
[str addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:NSMakeRange(18,2)];

属性については、 https ://developer.apple.com/documentation/foundation/nsattributedstringkey?language=objc で説明しています。

于 2015-07-27T17:45:45.710 に答える