用另一个NSAttributedString替换NSAttributedString的子字符串

用另一个NSAttributedString替换NSAttributedString的子字符串,string,cocoa,replace,nsattributedstring,foundation,String,Cocoa,Replace,Nsattributedstring,Foundation,我想用另一个NSAttributedString替换NSAttributedString的子字符串(例如@“替换”) 我正在为NSAttributedString寻找与NSString等效的方法 将属性化字符串转换为NSMutableAttributedString的实例 可变属性字符串具有mutableString属性。根据文件: “接收方跟踪对此字符串的更改,并使其属性映射保持最新。” 因此,您可以使用生成的可变字符串执行替换,替换为replaceConcurrencesofString:w

我想用另一个
NSAttributedString
替换
NSAttributedString
的子字符串(例如
@“替换”

我正在为
NSAttributedString
寻找与
NSString
等效的方法

  • 将属性化字符串转换为
    NSMutableAttributedString
    的实例

  • 可变属性字符串具有
    mutableString
    属性。根据文件:

    “接收方跟踪对此字符串的更改,并使其属性映射保持最新。”

    因此,您可以使用生成的可变字符串执行替换,替换为
    replaceConcurrencesofString:with字符串:选项:范围:


  • 以下是如何更改NSMutableAttributedString的字符串,同时保留其属性:

    Swift:

    // first we create a mutable copy of attributed text 
    let originalAttributedText = nameLabel.attributedText?.mutableCopy() as! NSMutableAttributedString
    
    // then we replace text so easily
    let newAttributedText = originalAttributedText.mutableString.setString("new text to replace")
    
    NSMutableAttributedString *newAttrStr = [attribtedTxt.mutableString setString:@"new string"];
    
    目标-C:

    // first we create a mutable copy of attributed text 
    let originalAttributedText = nameLabel.attributedText?.mutableCopy() as! NSMutableAttributedString
    
    // then we replace text so easily
    let newAttributedText = originalAttributedText.mutableString.setString("new text to replace")
    
    NSMutableAttributedString *newAttrStr = [attribtedTxt.mutableString setString:@"new string"];
    

    我必须在
    标记中使用粗体文本,以下是我所做的:

    - (NSAttributedString *)boldString:(NSString *)string {
        UIFont *boldFont = [UIFont boldSystemFontOfSize:14];
        NSMutableAttributedString *attributedDescription = [[NSMutableAttributedString alloc] initWithString:string];
    
        NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@".*?<b>(.*?)<\\/b>.*?" options:NSRegularExpressionCaseInsensitive error:NULL];
        NSArray *myArray = [regex matchesInString:string options:0 range:NSMakeRange(0, string.length)] ;
        for (NSTextCheckingResult *match in myArray) {
            NSRange matchRange = [match rangeAtIndex:1];
            [attributedDescription addAttribute:NSFontAttributeName value:boldFont range:matchRange];
        }
        while ([attributedDescription.string containsString:@"<b>"] || [attributedDescription.string containsString:@"</b>"]) {
            NSRange rangeOfTag = [attributedDescription.string rangeOfString:@"<b>"];
            [attributedDescription replaceCharactersInRange:rangeOfTag withString:@""];
            rangeOfTag = [attributedDescription.string rangeOfString:@"</b>"];
            [attributedDescription replaceCharactersInRange:rangeOfTag withString:@""];
        }
        return attributedDescription;
    }
    
    -(NSAttributedString*)boldString:(NSString*)字符串{
    UIFont*boldFont=[UIFont boldSystemFontOfSize:14];
    NSMutableAttributedString*attributedDescription=[[NSMutableAttributedString alloc]initWithString:string];
    NSRegularExpression*regex=[NSRegularExpression regularExpressionWithPattern:@.*?(.*?.*?。?*???。?”选项:NSRegularExpression不区分大小写错误:NULL];
    NSArray*myArray=[regex-matchesisnstring:string-options:0-range:NSMakeRange(0,string.length)];
    for(NSTextCheckingResult*匹配myArray){
    NSRange matchRange=[匹配范围索引:1];
    [attributedDescription addAttribute:NSFontAttributeName值:粗体字体范围:匹配范围];
    }
    而([attributedDescription.string包含字符串:@”“]| |[attributedDescription.string包含字符串:@”“){
    NSRange rangeOfTag=[attributedDescription.string rangeOfString:@”“;
    [attributedDescription ReplaceCharactersRange:带字符串的标记范围:@”“;
    rangeOfTag=[attributedDescription.string rangeOfString:@”“;
    [attributedDescription ReplaceCharactersRange:带字符串的标记范围:@”“;
    }
    返回属性描述;
    }
    
    在我的例子中,以下方法是唯一的(在iOS9上测试):


    当然,找到另一个更好的方法会很好。

    我发现所有其他答案都不起作用。下面是我如何替换类别扩展中NSAttributed字符串的内容:

    func stringWithString(stringToReplace:String, replacedWithString newStringPart:String) -> NSMutableAttributedString
    {
        let mutableAttributedString = mutableCopy() as! NSMutableAttributedString
        let mutableString = mutableAttributedString.mutableString
    
        while mutableString.containsString(stringToReplace) {
            let rangeOfStringToBeReplaced = mutableString.rangeOfString(stringToReplace)
            mutableAttributedString.replaceCharactersInRange(rangeOfStringToBeReplaced, withString: newStringPart)
        }
        return mutableAttributedString
    }
    

    使用Swift 4和iOS 11,您可以使用以下两种方法之一来解决问题


    #1.使用
    nsmutableAttributeString
    replaceCharacters(in:with:)
    方法
    nsmutableAttributeString
    有一个名为的方法
    replaceCharacters(in:with:)
    具有以下声明:

    将给定范围内的字符和属性替换为给定属性字符串的字符和属性

    下面的代码显示了如何使用
    replaceCharacters(in:with:)
    NSMutableAttributedString
    实例的子字符串替换为新的
    NSMutableAttributedString
    实例:

    import UIKit
    
    // Set initial attributed string
    let initialString = "This is the initial string"
    let attributes = [NSAttributedStringKey.foregroundColor : UIColor.red]
    let mutableAttributedString = NSMutableAttributedString(string: initialString, attributes: attributes)
    
    // Set new attributed string
    let newString = "new"
    let newAttributes = [NSAttributedStringKey.underlineStyle : NSUnderlineStyle.styleSingle.rawValue]
    let newAttributedString = NSMutableAttributedString(string: newString, attributes: newAttributes)
    
    // Get range of text to replace
    guard let range = mutableAttributedString.string.range(of: "initial") else { exit(0) }
    let nsRange = NSRange(range, in: mutableAttributedString.string)
    
    // Replace content in range with the new content
    mutableAttributedString.replaceCharacters(in: nsRange, with: newAttributedString)
    
    import UIKit
    
    // Set initial attributed string
    let initialString = "This is the initial string"
    let attributes = [NSAttributedStringKey.foregroundColor : UIColor.red]
    let mutableAttributedString = NSMutableAttributedString(string: initialString, attributes: attributes)
    
    // Set new string
    let newString = "new"
    
    // Replace replaceable content in mutableAttributedString with new content
    let totalRange = NSRange(location: 0, length: mutableAttributedString.string.count)
    _ = mutableAttributedString.mutableString.replaceOccurrences(of: "initial", with: newString, options: [], range: totalRange)
    
    // Get range of text that requires new attributes
    guard let range = mutableAttributedString.string.range(of: newString) else { exit(0) }
    let nsRange = NSRange(range, in: mutableAttributedString.string)
    
    // Apply new attributes to the text matching the range
    let newAttributes = [NSAttributedStringKey.underlineStyle : NSUnderlineStyle.styleSingle.rawValue]
    mutableAttributedString.setAttributes(newAttributes, range: nsRange)
    

    #2.使用
    NSMutableString
    replaceAccurrencess(of:with:options:range:)
    方法
    NSMutableString
    有一个名为的方法
    replaceAccurrencess(of:with:options:range:)
    具有以下声明:

    将给定范围内给定字符串的所有匹配项替换为另一个给定字符串,并返回替换次数

    下面的代码显示了如何使用
    replaceAccurrencess(of:with:options:range:)
    NSMutableAttributedString
    实例的子字符串替换为新的
    NSMutableAttributedString
    实例:

    import UIKit
    
    // Set initial attributed string
    let initialString = "This is the initial string"
    let attributes = [NSAttributedStringKey.foregroundColor : UIColor.red]
    let mutableAttributedString = NSMutableAttributedString(string: initialString, attributes: attributes)
    
    // Set new attributed string
    let newString = "new"
    let newAttributes = [NSAttributedStringKey.underlineStyle : NSUnderlineStyle.styleSingle.rawValue]
    let newAttributedString = NSMutableAttributedString(string: newString, attributes: newAttributes)
    
    // Get range of text to replace
    guard let range = mutableAttributedString.string.range(of: "initial") else { exit(0) }
    let nsRange = NSRange(range, in: mutableAttributedString.string)
    
    // Replace content in range with the new content
    mutableAttributedString.replaceCharacters(in: nsRange, with: newAttributedString)
    
    import UIKit
    
    // Set initial attributed string
    let initialString = "This is the initial string"
    let attributes = [NSAttributedStringKey.foregroundColor : UIColor.red]
    let mutableAttributedString = NSMutableAttributedString(string: initialString, attributes: attributes)
    
    // Set new string
    let newString = "new"
    
    // Replace replaceable content in mutableAttributedString with new content
    let totalRange = NSRange(location: 0, length: mutableAttributedString.string.count)
    _ = mutableAttributedString.mutableString.replaceOccurrences(of: "initial", with: newString, options: [], range: totalRange)
    
    // Get range of text that requires new attributes
    guard let range = mutableAttributedString.string.range(of: newString) else { exit(0) }
    let nsRange = NSRange(range, in: mutableAttributedString.string)
    
    // Apply new attributes to the text matching the range
    let newAttributes = [NSAttributedStringKey.underlineStyle : NSUnderlineStyle.styleSingle.rawValue]
    mutableAttributedString.setAttributes(newAttributes, range: nsRange)
    

    我有一个具体的要求和固定如下。这可能对某人有所帮助

    要求:在故事板中,富文本直接添加到UITextView的属性中,该属性包含一个单词“应用程序版本:1.0”。现在,我必须通过从info plist读取版本号来动态显示版本号

    解决方案: 从情节提要中删除了版本号1.0,只是保留了“应用程序版本:”并添加了以下代码

    NSAttributedString *attribute = self.firsttextView.attributedText;
    NSMutableAttributedString *mutableAttri = [[NSMutableAttributedString alloc] initWithAttributedString:attribute];
    NSString *appVersionText = @"App Version:";
    if ([[mutableAttri mutableString] containsString:appVersionText]) {
        NSDictionary* infoDict = [[NSBundle mainBundle] infoDictionary];
        NSString* version = [infoDict objectForKey:@"CFBundleShortVersionString"];
        NSString *newappversion = [NSString stringWithFormat:@"%@ %@",appVersionText,version] ;
        [[mutableAttri mutableString] replaceOccurrencesOfString:appVersionText withString:newappversion options:NSCaseInsensitiveSearch range:NSMakeRange(0, mutableAttri.length)];
        self.firsttextView.attributedText = mutableAttri;
    }
    
    完成!!更新/修改属性文本。

    Swift 4:
    更新了Swift 4的优秀解决方案,并以“扩展”包装。只需将其剪辑到ViewController(类外)并使用它

    extension NSAttributedString {
        func stringWithString(stringToReplace: String, replacedWithString newStringPart: String) -> NSMutableAttributedString
        {
            let mutableAttributedString = mutableCopy() as! NSMutableAttributedString
            let mutableString = mutableAttributedString.mutableString
            while mutableString.contains(stringToReplace) {
                let rangeOfStringToBeReplaced = mutableString.range(of: stringToReplace)
                mutableAttributedString.replaceCharacters(in: rangeOfStringToBeReplaced, with: newStringPart)
            }
            return mutableAttributedString
        }
    }
    

    这不是私有API吗?因为可变字符串属性是只读的?@MichalShatz否。只读属性意味着您不能为其分配其他对象(即,您不能调用
    setMutableString:
    )。但在适当的位置修改可变字符串对象是完全正确的。这就是这个属性存在的全部原因。这真的是一个答案吗?第二个参数(withString)是AttributedStrings,我遇到了一个强制转换问题方法“ReplaceCurrencesOfString:withString:options:range:”应用于NSMutableString,而不是NSAttributedString或NSMutableAttributedString。如果转换为NSMutableString并在此处进行替换,则转换后将丢失其属性。问题是如何获得NSAttributedString作为结果,而不仅仅是字符串,因此答案完全不相关,但它得到了如此多的支持票。这很好,例如替换新行字符:
    [[result mutableString]replaceCurrencesofString:@“\n”with string:@”“选项:NSCaseInsensitiveSearch范围:NSMakeRange(0,result.length)];您的示例甚至可能无法编译。存储在NSMutableAttributeString中的C字符串?替换无效,因为您在未引用的情况下对副本(
    mutableString
    )进行了替换?这更适合替换给定范围内的字符串,而不是引用,因为字符串可能包含重复的子字符串。用于替换给定范围内的文本(