我正在创建一个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)];
}
答案 0 :(得分:9)
在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};
答案 1 :(得分:4)
这是适用于我的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)
答案 2 :(得分:0)
改进/更正了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个左对齐制表符的数组。
此答案可以解决此问题,并且通过删除(不必要的?)“选项”以及使用循环(使其更简洁)(仅适用于所有制表符间距一致且对齐方式相同的情况)类型)。
答案 3 :(得分:-1)
ios 6.1添加了NSParagraphStyle,但似乎CTParagraphStyleRef和NSParagraphStyle不是免费的桥接。
结果如果您在NSAttributeString中有CTParagraphStyleRef,则会导致:
[__ NSCFType headIndent]:无法识别的选择器发送到实例xxxx
和NSParagraphStyle的其他方法,如对齐。