【发布时间】:2016-07-04 19:10:32
【问题描述】:
我找不到任何适用于在 NSTextField 和 NumberFormatter 中使用属性文本的主题。我想要完成的非常简单。我想在带有属性文本的可编辑NSTextField 上使用NumberFormatter,并保留文本属性。
目前,我已将NSTextFieldCell 子类化并实现它:
class AdjustTextFieldCell: NSTextFieldCell {
required init(coder: NSCoder) {
super.init(coder: coder)
let attributes = makeAttributes()
allowsEditingTextAttributes = true
attributedStringValue = AttributedString(string: stringValue, attributes: attributes)
//formatter = TwoDigitFormatter()
}
func makeAttributes() -> [String: AnyObject] {
let style = NSMutableParagraphStyle()
style.minimumLineHeight = 100
style.maximumLineHeight = 100
style.paragraphSpacingBefore = 0
style.paragraphSpacing = 0
style.alignment = .center
style.lineHeightMultiple = 1.0
style.lineBreakMode = .byTruncatingTail
let droidSansMono = NSFont(name: "DroidSansMono", size: 70)!
return [NSParagraphStyleAttributeName: style, NSFontAttributeName: droidSansMono, NSBaselineOffsetAttributeName: -60]
}
}
此实现调整 NSTextField 实例中的文本以具有显示的属性。当我取消注释设置 formatter 属性的行时,NSTextField 将失去其属性。我的NumberFormatter如下:
class TwoDigitFormatter: NumberFormatter {
override init() {
super.init()
let customAttribs = makeAttributes()
textAttributesForNegativeValues = customAttribs.attribs
textAttributesForPositiveValues = customAttribs.attribs
textAttributesForZero = customAttribs.attribs
textAttributesForNil = customAttribs.attribs
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
let maxLength = 2
let wrongCharacterSet = CharacterSet(charactersIn: "0123456789").inverted
override func isPartialStringValid(_ partialString: String, newEditingString newString: AutoreleasingUnsafeMutablePointer<NSString?>?, errorDescription error: AutoreleasingUnsafeMutablePointer<NSString?>?) -> Bool {
if partialString.characters.count > maxLength {
return false
}
if partialString.rangeOfCharacter(from: wrongCharacterSet) != nil {
return false
}
return true
}
override func attributedString(for obj: AnyObject, withDefaultAttributes attrs: [String : AnyObject]? = [:]) -> AttributedString? {
let stringVal = string(for: obj)
guard let string = stringVal else { return nil }
let customAttribs = makeAttributes()
var attributes = attrs
attributes?[NSFontAttributeName] = customAttribs.font
attributes?[NSParagraphStyleAttributeName] = customAttribs.style
attributes?[NSBaselineOffsetAttributeName] = customAttribs.baselineOffset
return AttributedString(string: string, attributes: attributes)
}
func makeAttributes() -> (font: NSFont, style: NSMutableParagraphStyle, baselineOffset: CGFloat, attribs: [String: AnyObject]) {
let style = NSMutableParagraphStyle()
style.minimumLineHeight = 100
style.maximumLineHeight = 100
style.paragraphSpacingBefore = 0
style.paragraphSpacing = 0
style.alignment = .center
style.lineHeightMultiple = 1.0
style.lineBreakMode = .byTruncatingTail
let droidSansMono = NSFont(name: "DroidSansMono", size: 70)!
return (droidSansMono, style, -60, [NSParagraphStyleAttributeName: style, NSFontAttributeName: droidSansMono, NSBaselineOffsetAttributeName: -60])
}
}
你可以从上面的代码中看到我已经尝试过:
- 设置
textAttributesFor...属性。 - 覆盖
attributedString(for obj: AnyObject, withDefaultAttributes attrs: [String : AnyObject]? = [:])
我已经分别尝试了这两种解决方案,也分别尝试过,但都没有成功。
TLDR:
是否可以同时使用属性文本和NumberFormatter?如果是这样,怎么做?如果没有,我如何将带有属性文本的NSTextField 限制为仅数字和两个字符而不使用NumberFormatter?
【问题讨论】:
-
什么对你不起作用?我试过这个(实际上简化了一点:gist.github.com/robertmryan/998a452a9a83eb4dbec4bebd2da52337),它似乎工作正常。我正在尝试了解您所经历的行为以及与您的预期有何不同?
-
@CodeDifferent 我正在使用 Swift 3。
-
@Rob 我期望的行为是
NSTextField中的文本将根据NumberFormatter进行格式化,但保留其属性。它与我的预期不同,因为NSTextField中的文本已格式化但丢失了它的属性(即字体、段落样式等)。您发布的代码似乎对我不起作用。除了连接@IBOutlet之外,您在 Main.storyboard 文件中还做了什么? -
编辑时,属性样式不存在,但是当您离开文本字段并转到另一个文本字段时,属性文本样式会重新出现。如果您返回并编辑,格式会再次消失,直到您完成编辑。这是你看到的行为吗?
-
@Rob 仔细检查,格式保留在您的代码中,但在编辑
NSTextField时不会。有没有办法在编辑NSTextField期间保留属性?
标签: swift cocoa nsattributedstring nstextfield nsnumberformatter