我正在创建一个iOS应用,我想使用在UITextView中指定的特定制表位。我也想画使用drawRect中的Core Text直接导入UIViews中。我想要(如果可能)对于在两种情况下都将使用的相同属性字符串。
因此,在我的应用中,我创建了CFAttributedStringRef或NSAttributedString,将CTParagraphStyle属性应用于它。然后,我尝试显示UITextView中的属性字符串,出现如下所示的崩溃:
-[__NSCFType headIndent]: unrecognized selector sent to instance 0x7545080
po 0x7545080
$0 = 122966144 CTParagraphStyle:
base writing direction = -1, alignment = 4, line break mode = 0,
default tab interval = 0
first line head indent = 0, head indent = 0, tail indent = 0
line height multiple = 0, maximum line height = 0, minimum line height = 0
line spacing adjustment = 0, paragraph spacing = 0,
paragraph spacing before = 0
tabs:
(
"CTTextTab: location = 20, alignment = 0, options = (none)\n",
"CTTextTab: location = 40, alignment = 0, options = (none)\n",
"CTTextTab: location = 60, alignment = 0, options = (none)\n",
"CTTextTab: location = 80, alignment = 0, options = (none)\n",
"CTTextTab: location = 100, alignment = 0, options = (none)\n",
"CTTextTab: location = 120, alignment = 0, options = (none)\n"
)
我了解发生了什么,但是我想知道是否还有其他方法做我想做的事。 iOS上的NSMutableParagraphStyle没有标签停止支持,但我注意到OS X上的NSMutableParagraphStyle确实有此功能能力。这使我认为iOS NSMutableParagraphStyle可能有一天支持这一点。
同时,是否可以将制表位添加到CFAttributedStringRef或NSAttributedString并仍然显示UITextView吗?
有问题的来源是:
- (void)viewWillAppear:(BOOL)animated
{
CFDictionaryRef attrs = (__bridge CFDictionaryRef) @{};
CFAttributedStringRef a = CFAttributedStringCreate(
kCFAllocatorDefault, CFSTR("a\tb\tc\td"), attrs);
CFMutableAttributedStringRef attrStr;
attrStr = CFAttributedStringCreateMutableCopy(
kCFAllocatorDefault, CFAttributedStringGetLength(a), a);
CFArrayRef tabStops = (__bridge CFArrayRef) @[
(__bridge id) CTTextTabCreate(0, 20, NULL),
(__bridge id) CTTextTabCreate(0, 40, NULL),
(__bridge id) CTTextTabCreate(0, 60, NULL),
(__bridge id) CTTextTabCreate(0, 80, NULL),
(__bridge id) CTTextTabCreate(0, 100, NULL),
(__bridge id) CTTextTabCreate(0, 120, NULL)];
const CTParagraphStyleSetting paraSettings[] = {
{kCTParagraphStyleSpecifierTabStops, sizeof(CFArrayRef), &tabStops},
};
CTParagraphStyleRef paraStyle = CTParagraphStyleCreate(
paraSettings,
sizeof(paraSettings) / sizeof(CTParagraphStyleSetting));
CFRange range = CFRangeMake(0, CFAttributedStringGetLength(attrStr));
CFAttributedStringSetAttribute(
attrStr, range, kCTParagraphStyleAttributeName, paraStyle);
CFRelease(paraStyle);
CFIndex i, count = CFArrayGetCount(tabStops);
for (i = 0; i < count; i++) {
CFRelease(CFArrayGetValueAtIndex(tabStops, i));
}
[[self textView] setAttributedText:
(__bridge NSAttributedString *)(attrStr)];
}
在iOS 7中,您可以这样操作:
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};
这是对我有用的Swift版本:
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)
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])
为什么要这个额外的Swift答案?
较早的Swift答案是有缺陷的,因为它在不先删除默认制表位的情况下添加了制表位(12个左对齐的制表位,间距为28 pt)。因此,它向默认的一组制表位添加了一组新的制表位,而不是将其替换为新的制表位。使用基于该答案的代码使我非常沮丧,试图弄清楚为什么它对我不起作用,直到我回到documentation for NSMutableParagraphStyle.tabStops并了解默认的制表位:
默认值是一个28点间隔的12个左对齐制表符的数组。
此答案可以解决此问题,并且通过删除(不必要的?)“选项”以及使用循环(使其更简洁)(仅在所有制表符间距一致且所有对齐类型均相同的情况下才适用) )。
ios 6.1添加了NSParagraphStyle,但CTParagraphStyleRef和NSParagraphStyle似乎不是免费的桥接。
因此,如果NSAttributeString中包含CTParagraphStyleRef,则会导致:
[__ NSCFType headIndent]:无法识别的选择器已发送到实例xxxx
和其他NSParagraphStyle方法,例如对齐。