通常我在界面构建器中构建app界面。有时设计需要使用属性字符串(字体,颜色等)。如果string是静态的,则很容易配置。
但是如果string是动态的(带参数的格式),则无法在界面构建器中配置属性。它需要编写大量代码。
我正在为[NSString stringWithFormat:]
寻找NSAttributedString
的一些类似物。所以我将能够在界面构建器中设置字符串格式和必要的属性,然后在代码中提供必要的参数。
例如: 让我们考虑一下我需要这样格式的显示字符串:“%d +%d =%d”(所有数字都是粗体)。 我想在界面构建器中配置此格式。在代码中我想提供参数:1,1,2。应该显示“1 + 1 = 2”。
我一直在寻找这个问题的现有解决方案,但没有成功。 所以我能够自己实现它。 这就是为什么我要自我回答与社区分享知识的问题。
NSAttributedString+VPAttributedFormat类提供了基于属性格式和应满足此格式的参数构建属性字符串的方法。 使用此类别的最合适的情况是在界面构建器中配置的具有可变属性文本的文本控件。 您需要为归属文本设置正确的字符串格式并配置必要的属性。 然后,您需要使用此类别的方法在代码中传递必要的参数。
[NSString stringWithFormat:]
方法相同;1.导入框架标题或模块
// Objective C
// By header
#import <VPAttributedFormat/VPAttributedFormat.h>
// By module
@import VPAttributedFormat;
// Swift
import VPAttributedFormat
2.在界面生成器中为文本控件设置正确的格式和属性
3.创建IBOutlet并将其与文本控件链接
// Objective C
@property (nonatomic, weak) IBOutlet UILabel *textLabel;
// Swift
@IBOutlet weak var textLabel: UILabel!
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格式示例。
这是我写的一个类别,用于将方法添加到NSAttributedString。您必须传入NULL作为函数的最后一个参数,否则它将崩溃到检测大小的va_list限制。 [attributionString stringWithFormat:attrFormat,attrArg1,attrArg2,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
这是一个基于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)
}
}
兼容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)
结果: