I'm trying to learn about NSMutableAttributedString
and NSAttributedString
so I've created a simple playground to try some things. However, I have a couple of issues I can't figure out even after looking at a lot of examples on SO (like here and NSRange from Swift Range? elsewhere.
The problem is with the length property. If I specify the length as attribLabelText.length
it causes an uncaught exception. If I specify attribLabelText.length - 1
there's no error, but only the letters 'Repor' have the attributes I'm setting:
import UIKit
import PlaygroundSupport
class MyViewController : UIViewController {
override func loadView() {
let view = UIView()
view.backgroundColor = .white
let label = getLabel1(labelText: "Report")
view.addSubview(label)
self.view = view
}
}
func getLabel1(labelText: String) -> UILabel {
let label = UILabel()
label.frame = CGRect(x: 150, y: 200, width: 200, height: 20)
label.textColor = .black
let attribLabelText: NSMutableAttributedString = NSMutableAttributedString(string: labelText)
let attributes = [
NSAttributedString.Key.foregroundColor : UIColor.gray.cgColor,
NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 14)
] as [NSAttributedString.Key : Any]
attribLabelText.addAttributes(attributes, range: NSRange(location: 0, length: attribLabelText.length)) <-- this causes an uncaught exception of type NSException
label.attributedText = attribLabelText
return label
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
I have a feeling this is going to be something obvious but I'm out of ideas to try. Can anybody point out what I'm doing wrong?
You should be passing a UIColor
for the foreground color instead of a CGColor
.
UILabel seems to use the foreground color attribute slightly differently when drawing the string based on whether the attribute covers the entire range of the string or just a subrange.
The version it uses when the attribute covers the entire string only works with UIColor
but the version it uses when the attribute only covers a substring seems to also work with CGColor
(though this behavior isn't documented so it shouldn't be relied on) which explains why adding the -1 to the range avoids the exception.