Skip to content

Instantly share code, notes, and snippets.

@rintaro
Created November 28, 2014 18:34
Show Gist options
  • Save rintaro/4d6c34ae54401286cc25 to your computer and use it in GitHub Desktop.
Save rintaro/4d6c34ae54401286cc25 to your computer and use it in GitHub Desktop.
NSAttributedString from NSAttributedString format
//
// NSAttributedString+AttributedFormat.h
// AttributedFormat
//
// Created by rintaro on 11/28/14.
// Copyright (c) 2014 rintaro. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface NSAttributedString (AttributedFormat)
- (instancetype)initWithFormat:(NSAttributedString *)attrFormat, ...;
- (instancetype)initWithFormat:(NSAttributedString *)attrFormat arguments:(va_list)arguments;
@end
//
// NSAttributedString+AttributedFormat.m
// AttributedFormat
//
// Created by rintaro on 11/28/14.
// Copyright (c) 2014 rintaro. All rights reserved.
//
#import "NSAttributedString+AttributedFormat.h"
@implementation NSAttributedString (AttributedFormat)
- (instancetype)initWithFormat:(NSAttributedString *)attrFormat, ... {
va_list args;
va_start(args, attrFormat);
self = [self initWithFormat:attrFormat arguments:args];
va_end(args);
return self;
}
- (instancetype)initWithFormat:(NSAttributedString *)attrFormat arguments:(va_list)arguments {
NSRegularExpression *regex;
regex = [[NSRegularExpression alloc] initWithPattern: @"(%.*?[@%dDuUxXoOfeEgGccsSpaAF])"
options: 0
error: nil];
NSString *format = attrFormat.string;
format = [regex stringByReplacingMatchesInString: format
options: 0
range: NSMakeRange(0, format.length)
withTemplate: @"\0$1\0"];
NSLog(@"%@", format);
//va_list args;
//va_copy(args, arguments);
NSString *result = [[NSString alloc] initWithFormat:format arguments:arguments];
//va_end(args);
NSMutableArray *f_comps = [format componentsSeparatedByString:@"\0"].mutableCopy;
NSMutableArray *r_comps = [result componentsSeparatedByString:@"\0"].mutableCopy;
NSMutableAttributedString *output = [[NSMutableAttributedString alloc] init];
__block int consumed_length = 0;
[attrFormat enumerateAttributesInRange:NSMakeRange(0, attrFormat.length) options:0 usingBlock:^(NSDictionary *attrs, NSRange range, BOOL *stop) {
NSMutableString *substr = [NSMutableString string];
while(f_comps.count > 0 && NSMaxRange(range) >= consumed_length + [(NSString *)f_comps[0] length]){
NSString *f_str = f_comps[0];
NSString *r_str = r_comps[0];
[substr appendString:r_str];
[f_comps removeObjectAtIndex:0];
[r_comps removeObjectAtIndex:0];
consumed_length += f_str.length;
}
NSUInteger idx = NSMaxRange(range) - consumed_length;
if(f_comps.count > 0 && idx > 0) {
NSString *f_str = f_comps[0];
NSString *leading = [f_str substringToIndex:idx];
[substr appendString:leading];
NSString *trailing = [f_str substringFromIndex:idx];
[f_comps replaceObjectAtIndex:0 withObject:trailing];
[r_comps replaceObjectAtIndex:0 withObject:trailing];
consumed_length += idx;
}
[output appendAttributedString:[[NSAttributedString alloc] initWithString:substr attributes:attrs]];
}];
return [self initWithAttributedString:output];
}
@end
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *formatLabel;
@property (weak, nonatomic) IBOutlet UILabel *resultLabel;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSMutableAttributedString *fmt = [[NSMutableAttributedString alloc] initWithString:@"test: "];
[fmt appendAttributedString: [[NSAttributedString alloc] initWithString: @"Some%%string"
attributes: @{
NSFontAttributeName: [UIFont systemFontOfSize:17]
}]];
[fmt appendAttributedString: [[NSAttributedString alloc] initWithString: @"bold %@ template %.3f %d"
attributes: @{
NSFontAttributeName: [UIFont boldSystemFontOfSize:20],
NSForegroundColorAttributeName: [UIColor redColor]
}]];
[fmt appendAttributedString: [[NSAttributedString alloc] initWithString: @"%@ blah blah blah"
attributes: @{
NSFontAttributeName: [UIFont systemFontOfSize:16],
NSForegroundColorAttributeName: [UIColor blueColor]
}]];
NSAttributedString *result = [[NSAttributedString alloc] initWithFormat:fmt, @"[foo]", 1.23, 56, @"[[bar]]"];
self.formatLabel.attributedText = fmt;
self.resultLabel.attributedText = result;
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment