ios 对于NSAttributedString,是否有类似于[NSString字符串格式:]的内容

mwkjh3gx  于 2023-03-09  发布在  iOS
关注(0)|答案(5)|浏览(135)

我通常在界面生成器中构建应用界面。有时候设计需要使用属性字符串(字体、颜色等)。如果字符串是静态的,那么很容易配置。
但是如果字符串是动态的(带参数的格式),那么就没有办法在接口生成器中配置属性,这需要编写大量的代码。
我正在为NSAttributedString寻找一些[NSString stringWithFormat:]的类似物。这样我就可以在接口构建器中设置字符串格式和必要的属性,然后在代码中提供必要的参数。

例如:

让我们考虑一下,我需要这样的格式显示字符串:“%d+%d=%d”(所有数字均为粗体)。
我想在接口生成器中配置此格式。在代码中我想提供参数:1、1、2。应用程序应显示“1+1=2"。

7lrncoxx

7lrncoxx1#

与Swift 4.2兼容

public extension NSAttributedString {
    convenience init(format: NSAttributedString, args: NSAttributedString...) {
        let mutableNSAttributedString = NSMutableAttributedString(attributedString: format)

        args.forEach { (attributedString) in
            let range = NSString(string: mutableNSAttributedString.string).range(of: "%@")
            mutableNSAttributedString.replaceCharacters(in: range, with: attributedString)
        }
        self.init(attributedString: mutableNSAttributedString)
    }
}

用法:

let content = NSAttributedString(string: "The quick brown %@ jumps over the lazy %@")
let fox = NSAttributedString(string: "fox", attributes: [.font: Fonts.CalibreReact.boldItalic.font(size: 40)])
let dog = NSAttributedString(string: "dog", attributes: [.font: Fonts.CalibreReact.lightItalic.font(size: 11)])
attributedLabel.attributedText = NSAttributedString(format: content, args: fox, dog)

结果:

slmsl1lt

slmsl1lt2#

我一直在寻找这个问题的现有解决方案,但没有成功。
所以我可以自己实现它。
这就是为什么我自己回答这个问题,与社区分享知识。
溶液
NSAttributedString+VPAttributedFormat类别提供了基于属性化格式和应满足此格式的参数构建属性化字符串的方法。
使用此类别最合适的情况是在接口生成器中配置了具有变量属性文本的文本控件。
您需要为属性化文本设置正确的字符串格式,并配置必要的属性。
然后,您需要使用此类方法在代码中传递必要的参数。

  • 格式语法同[NSString stringWithFormat:]方法;
  • 可用于Objective C和Swift代码;
  • 需要iOS 6.0及更高版本;
  • 与CocoaPods集成;
  • 包含在单元测试中。

用法

1.导入框架头或模块

// Objective C
// By header
#import <VPAttributedFormat/VPAttributedFormat.h>

// By module
@import VPAttributedFormat;
// Swift
import VPAttributedFormat

2.在界面生成器中为文本控件设置正确的格式和属性

3.创建IBOutlet并将其与文本控件链接

一个二个一个一个

4.使用必要的参数填充格式

// Objective C
NSString *hot = @"Hot";
NSString *cold = @"Cold";
  
self.textLabel.attributedText = [NSAttributedString vp_attributedStringWithAttributedFormat:self.textLabel.attributedText,
                                 hot,
                                 cold];
// Swift
let hot = "Hot"
let cold = "Cold"
var arguments: [CVarArgType] = [hot, cold]
textLabel.attributedText = withVaList(arguments) { pointer in
    NSAttributedString.vp_attributedStringWithAttributedFormat(textLabel.attributedText, arguments: pointer)
}

5.参见结果

示例

VPAttributedFormatExample是一个示例项目,它提供了Basic和Pro格式的示例。

xoshrz7s

xoshrz7s3#

这是我写的一个类别,用来将方法添加到NSAttributedString中。但是,您必须将NULL作为最后一个参数传递给函数,否则,它将在检测大小时崩溃到va_list限制。[attributedString stringWithFormat:attrFormat,attrArg 1,attrArg 2,NULL];

@implementation NSAttributedString(stringWithFormat)

+(NSAttributedString*)stringWithFormat:(NSAttributedString*)format, ...{
    va_list args;
    va_start(args, format);

    NSMutableAttributedString *mutableAttributedString = (NSMutableAttributedString*)[format mutableCopy];
    NSString *mutableString = [mutableAttributedString string];

    while (true) {
        NSAttributedString *arg = va_arg(args, NSAttributedString*);
        if (!arg) {
            break;
        }
        NSRange rangeOfStringToBeReplaced = [mutableString rangeOfString:@"%@"];
        [mutableAttributedString replaceCharactersInRange:rangeOfStringToBeReplaced withAttributedString:arg];
    }

    va_end(args);

    return mutableAttributedString;
}
@end
67up9zun

67up9zun4#

以下是基于TheJeff答案的Swift 4扩展(更正了多次替换),它仅限于用NSAttributedString替换占位符:

public extension NSAttributedString {
    convenience init(format: NSAttributedString, args: NSAttributedString...) {
        let mutableNSAttributedString = NSMutableAttributedString(attributedString: format)

        var nsRange = NSString(string: mutableNSAttributedString.string).range(of: "%@")
        var param = 0
        while nsRange.location != NSNotFound {
            guard args.count > 0, param < args.count else {
                fatalError("Not enough arguments provided for \(format)")
            }

            mutableNSAttributedString.replaceCharacters(in: nsRange, with: args[param])
            param += 1
            nsRange = NSString(string: mutableNSAttributedString.string).range(of: "%@")
        }

        self.init(attributedString: mutableNSAttributedString)
    }
}
vecaoik1

vecaoik15#

其他一些答案假设参数的顺序是固定的,但使用由NSLocalizedString()返回的本地化字符串时不一定如此。以下代码考虑到了这一点。它假设格式字符串只包含%@说明符(例如,当存在单个自变量或非本地化字符串时),或%1$@%2$@%3$@等的序列,允许它们在格式字符串中更改位置,并且仍然Map到正确的参数:

extension NSMutableAttributedString {
    
    private static let formatRegex = try! NSRegularExpression(pattern: "%(?:(\\d+)\\$)?@")
    
    convenience init(format: String, arguments: [NSAttributedString]) {
        self.init(string: format)
        var i = 0
        var location = 0
        while let match = NSMutableAttributedString.formatRegex.firstMatch(in: string, range: NSRange(location: location, length: length - location)) {
            let index = match.range(at: 1).location == NSNotFound ? i : Int((string as NSString).substring(with: match.range(at: 1)))! - 1
            let argument = arguments[index]
            addAttributes(argument.attributes(at: 0, effectiveRange: nil), range: match.range)
            replaceCharacters(in: match.range, with: argument.string)
            i += 1
            location = match.range.location + argument.length
        }
    }
    
}

用法:

let string = NSMutableAttributedString(format: "From %1$@ to %2$@.", arguments: [
    NSAttributedString(string: "left", attributes: [.foregroundColor: NSColor.red]),
    NSAttributedString(string: "right", attributes: [.foregroundColor: NSColor.blue])
])

如果愿意,可以让它接受可变参数而不是数组:

convenience init(format: String, arguments: NSAttributedString...) {
    ...
}

相关问题