这里和文字相关的,一般涉及到NSTextStorage(文本编辑)、NSFont(字体)和NSFontDescriptor(字体信息描述)、NSFontManager(字体管理器)
首先要textView(统一用它代表NSTextView的实例)得到选中的范围:
NSArray *aArray = textView.selectedRanges;
if(!aArray || aArray.count==0)
{
return;
}
NSRange selectedRange = [(NSValue *)[aArray objectAtIndex:0] rangeValue]; //常见的选中范围是一个,想要通用,可以for一把
想要修改文字属性,需要通知textStorage:
NSTextStorage *textStorage = [textView textStorage];
[textStorage beginEditing]; //开始编辑
//这里是编辑过程。。。。
[textStorage endEditing]; //结束编辑
最后需要通知textView文本已经更新了:
[textView didChangeText];
整个流程已经实现,打完收工?
不不不,上面是总括流程,还有中间细节需要处理(编辑过程)
这里需要用到NSTextStorage的操作
- (void)enumerateAttributesInRange:(NSRange)enumerationRange options:(NSAttributedStringEnumerationOptions)opts usingBlock:(void (NS_NOESCAPE ^)(NSDictionary<NSAttributedStringKey, id> *attrs, NSRange range, BOOL *stop))block API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0));
这个操作主要是枚举选中范围内的所有字体属性,例如我们选中“123ABC“,其中123已经是粗体,但是ABC不是,这里就可能枚举出2个范围,也可能更多,比如123是Arial,AB可能是宋体,C可能其他字体。所有必须枚举完这些,注意修改属性。
如上述,选中的文字包含粗体和非粗体的,在著名的编辑软件都是先同意修改成粗体或非粗体,我选择是对第一个枚举的范围属性做标识,然后后面的都根据第一个标识统一修改。
这里需要用到穿越block的参数标识”__block“。
在块里面,可以得到通过NSDictionary *attributesDictionary传递的字体信息
NSFont *font = [attributesDictionary objectForKey:NSFontAttributeName];
然后对font分析是否已经设置为粗体:
NSFontDescriptor *desc=font.fontDescriptor;
NSFontDescriptorSymbolicTraits symbolic_traits=desc.symbolicTraits;
if (!hasChange)
{
hasChange=YES;
//NSFontDescriptorTraitBold == NSBoldFontMask
if ((symbolic_traits & NSFontDescriptorTraitBold)==0) {
//if not bold then set to bold
bold_flag=1;
}
}
通过将font放置到通用的NSFontManager,然后进行修改,重新读出来:
NSUInteger traits = (NSUInteger)symbolic_traits;
NSFontManager *fontManager = [NSFontManager sharedFontManager];
[fontManager setSelectedFont:font isMultiple:NO];
//weight(0~9);default=5
font = [fontManager fontWithFamily:font.familyName traits:(traits) weight:5 size:(font.pointSize)];
对选中字体切换字体的过程就这么多。中间还有一个很小很小的细节留给读者补充^_^