Skip to content

Instantly share code, notes, and snippets.

@beccadax
Created May 5, 2014 20:28
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save beccadax/11546648 to your computer and use it in GitHub Desktop.
Save beccadax/11546648 to your computer and use it in GitHub Desktop.
Do simple +stringWithFormat:-type operations with NSAttributedString.
//
// NSAttributedString+format.m
// Chatterbox
//
// Created by Brent Royal-Gordon on 2/7/14.
// Copyright (c) 2014 Architechies. All rights reserved.
//
#import "NSAttributedString+format.h"
@implementation NSAttributedString (format)
- (instancetype)initWithFormat:(NSString *)format attributes:(NSDictionary *)attrs argumentAttributes:(NSDictionary *)argAttrs arguments:(va_list)argList {
NSMutableAttributedString * text = [[NSMutableAttributedString alloc] initWithString:@"" attributes:attrs];
NSScanner * scanner = [NSScanner scannerWithString:format];
scanner.charactersToBeSkipped = [NSCharacterSet new];
while (![scanner isAtEnd]) {
NSString * discarded;
[scanner scanUpToString:@"%" intoString:&discarded];
if(discarded) {
[text appendAttributedString:[[NSAttributedString alloc] initWithString:discarded attributes:attrs]];
}
if([scanner scanString:@"%%" intoString:NULL]) {
[text appendAttributedString:[[NSAttributedString alloc] initWithString:@"%" attributes:attrs]];
}
else if([scanner scanString:@"%@" intoString:NULL]) {
id object = va_arg(argList, id);
if(![object isKindOfClass:NSAttributedString.class]) {
object = [[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@", object] attributes:argAttrs];
}
[text appendAttributedString:object];
}
else if([scanner scanString:@"%" intoString:NULL]) {
NSString * specifier = [format substringFromIndex:scanner.scanLocation];
if(specifier.length > 1) {
specifier = [specifier substringToIndex:1];
}
NSAssert(NO, @"Unsupported format specifier '%@'", specifier);
}
}
return text;
}
- (instancetype)initWithFormat:(NSString *)format attributes:(NSDictionary *)attrs argumentAttributes:(NSDictionary *)argAttrs, ... {
va_list args;
va_start(args, argAttrs);
NSAttributedString * text = [self initWithFormat:format attributes:attrs argumentAttributes:argAttrs arguments:args];
va_end(args);
return text;
}
@end
@robrix
Copy link

robrix commented May 5, 2014

Very nice!

My approach to this was a constructor with a regexp, %(\d+)\$@, and an array of attributed strings to interpolate.

@centerThread
Copy link

Really like the concept, but having an issue va_arg(argList, id) going to nil on the second object, is NSDictionary correct? Is there an example that implements this category?

@erdnussflips
Copy link

Hello @brentax, is it allowed to use this gist in source code of a commercial application?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment