I\'m creating an iOS app, and I would like to display an attributed string with specific tab stops specified in a UITextView. I would also like to draw them directly into U
Improved/Corrected Answer for Swift:
let tablInterval: CGFloat = 20.0
var tabsArray = [NSTextTab]()
for i in 1...6 {
tabsArray.append(NSTextTab(textAlignment: .Left, location: i*tabInterval, options: [:]))
}
let paraStyle = NSMutableParagraphStyle()
paraStyle.tabStops = tabsArray
textView.attributedString = NSAttributedString(string: text, attributes: [NSAttributedString.Key.ParagraphStyle: paraStyle])
Why this extra Swift Answer?
The earlier Swift answer is flawed because it adds tab stops without first removing the default tab stops (12 left-aligned tab stops at 28 pt spacing). Therefore it adds a new set of tab stops to the default set of tab stops instead of replacing them with the new set of tab stops. Using code based on that answer caused me a great deal of frustration trying to figure out why it did not work for me, until I went back to the documentation for NSMutableParagraphStyle.tabStops and read about the default tab stops:
The default value is an array of 12 left-aligned tabs at 28-point intervals.
This answer corrects this, and is made more succinct by removing the (unecessary?) 'options' as well as using a loop (which is only suitable in cases where all the tabs are at consistent spacing and all with the same alignment type).
In iOS 7 you can do it like this:
UIFont *font = [UIFont systemFontOfSize:18.0];
NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
NSInteger cnt;
CGFloat tabInterval = 72.0;
paragraphStyle.defaultTabInterval = tabInterval;
NSMutableArray *tabs = [NSMutableArray array];
for (cnt = 1; cnt < 13; cnt++) { // Add 12 tab stops, at desired intervals...
[tabs addObject:[[NSTextTab alloc] initWithTextAlignment:NSTextAlignmentLeft location:tabInterval * cnt options:nil]];
}
paragraphStyle.tabStops = tabs;
NSDictionary *attributes = @{ NSFontAttributeName: font, NSParagraphStyleAttributeName: paragraphStyle};
This is the Swift version that worked for me:
let tablInterval: CGFloat = 85.0
let paragraphStyle = NSMutableParagraphStyle()
let terms = NSTextTab.columnTerminatorsForLocale(NSLocale.currentLocale())
let tabStop0 = NSTextTab(textAlignment: .Right, location: 0, options: [NSTabColumnTerminatorsAttributeName:terms])
let tabStop1 = NSTextTab(textAlignment: .Right, location: tablInterval, options: [NSTabColumnTerminatorsAttributeName:terms])
let tabStop2 = NSTextTab(textAlignment: .Right, location: tablInterval*2, options: [NSTabColumnTerminatorsAttributeName:terms])
let tabStop3 = NSTextTab(textAlignment: .Right, location: tablInterval*3, options: [NSTabColumnTerminatorsAttributeName:terms])
paragraphStyle.addTabStop(tabStop0)
paragraphStyle.addTabStop(tabStop1)
paragraphStyle.addTabStop(tabStop2)
paragraphStyle.addTabStop(tabStop3)
let attributedString = NSMutableAttributedString(string:text)
attributedString.addAttribute(NSParagraphStyleAttributeName, value:paragraphStyle, range:rangeAll)
ios 6.1 added NSParagraphStyle but it seem the CTParagraphStyleRef and NSParagraphStyle are not toll free bridging.
As result if you have CTParagraphStyleRef in NSAttributeString it causes:
[__NSCFType headIndent]: unrecognized selector sent to instance xxxx
and other methods for NSParagraphStyle such as alignment.