Reputation: 1448
I'm moving from swift 3 to swift 4. I have UILabels that I am giving very specific text properties to the label. I'm getting an 'unexpectedly found nil while unwrapping optional value' error when strokeTextAttributes is being initialized. I'm totally lost to be frank.
In swift 3 the of strokeTextAttributes was [String : Any] but swift 4 threw errors until I changed it to what it is below.
let strokeTextAttributes = [
NSAttributedStringKey.strokeColor.rawValue : UIColor.black,
NSAttributedStringKey.foregroundColor : UIColor.white,
NSAttributedStringKey.strokeWidth : -2.0,
NSAttributedStringKey.font : UIFont.boldSystemFont(ofSize: 18)
] as! [NSAttributedStringKey : Any]
chevronRightLabel.attributedText = NSMutableAttributedString(string: "0", attributes: strokeTextAttributes)
Upvotes: 12
Views: 34388
Reputation: 1401
@Larme's comment about the .rawValue
not being needed is correct.
Also, you can avoid the force cast that crashes your code using explicit typing:
let strokeTextAttributes: [NSAttributedString.Key: Any] = [
.strokeColor : UIColor.black,
.foregroundColor : UIColor.white,
.strokeWidth : -2.0,
.font : UIFont.boldSystemFont(ofSize: 18)
]
This gets rid of the repetitive NSAttributedString.Key.
, too.
Upvotes: 31
Reputation: 4551
let text = systolicString + " / " + diastolicString
let newStr = NSMutableAttributedString(string: text)
// I have static ranges, but you can also extract them dynamically
let systolicRange = NSRange(location: 0, length: 2)
let backslashRange = NSRange(location: 3, length: 1)
let diastolicRange = NSRange(location: 5, length: 2)
newStr.addAttribute(NSAttributedStringKey.font, value: UIFont.ubuntuRegular(28), range: systolicRange)
newStr.addAttribute(NSAttributedStringKey.foregroundColor, value: UIColor(hexString: "042f57"), range: systolicRange)
newStr.addAttribute(NSAttributedStringKey.font, value: UIFont.ubuntuLight(23), range: backslashRange)
newStr.addAttribute(NSAttributedStringKey.foregroundColor, value: UIColor(hexString: "6485a3"), range: backslashRange)
newStr.addAttribute(NSAttributedStringKey.font, value: UIFont.ubuntuRegular(18), range: diastolicRange)
newStr.addAttribute(NSAttributedStringKey.foregroundColor, value: UIColor(hexString: "042f57"), range: diastolicRange)
// my UILabel
valueLabel.attributedText = newStr
Upvotes: 0
Reputation:
if you want to change particular string value so that below answer is helpful you:-
let subStr = "Hello" let allStr = "Hello World"
let newStr = NSMutableAttributedString(string: allStr)
newStr.addAttribute(kCTFontAttributeName as NSAttributedStringKey, value: UIFont.init(customFont: .MyriadPro_R, withSize: 18)!, range: (allStr as NSString).range(of: subStr))
newStr.addAttribute(NSAttributedStringKey.foregroundColor, value: UIColor.PrimaryColor, range: (allStr as NSString).range(of: subStr))
self.stateLbl.attributedText = newStr
Upvotes: 0
Reputation: 79656
In Swift 4.0+
, attributed string accepts json (dictionary) with key type NSAttributedStringKey
or NSAttributedString.Key
.
So you must change it from [String : Any]
to
Swift 4.1 & below - [NSAttributedStringKey : Any]
&
Swift 4.2 & above - [NSAttributedString.Key : Any]
Initialiser for AttributedString
in Swift 4.2 is changed to [NSAttributedString.Key : Any]?
public init(string str: String, attributes attrs: [NSAttributedString.Key : Any]? = nil)
Here is sample working code.
let label = UILabel()
let labelText = "String Text"
let strokeTextAttributes = [
NSAttributedString.Key.strokeColor : UIColor.black,
NSAttributedString.Key.foregroundColor : UIColor.white,
NSAttributedString.Key.strokeWidth : -2.0,
NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 18)
] as [NSAttributedString.Key : Any]
label.attributedText = NSAttributedString(string: labelText, attributes: strokeTextAttributes)
Initialiser for AttributedString
in Swift 4.0 is changed to [NSAttributedStringKey : Any]?
.
public init(string str: String, attributes attrs: [NSAttributedStringKey : Any]? = nil)
Here is sample working code.
let label = UILabel()
let labelText = "String Text"
let strokeTextAttributes = [
NSAttributedStringKey.strokeColor : UIColor.black,
NSAttributedStringKey.foregroundColor : UIColor.white,
NSAttributedStringKey.strokeWidth : -2.0,
NSAttributedStringKey.font : UIFont.boldSystemFont(ofSize: 18)
] as [NSAttributedStringKey : Any]
label.attributedText = NSAttributedString(string: labelText, attributes: strokeTextAttributes)
Look at this Apple Document, for more info: NSAttributedString - Creating an NSAttributedString Object
Upvotes: 16
Reputation: 14372
In Swift 4.x, this should look like :
let strokeTextAttributes: [NSAttributedStringKey: Any] = [
NSStrokeColorAttributeName: UIColor.black,
NSForegroundColorAttributeName : UIColor.white,
NSStrokeWidthAttributeName : -2.0,
NSFontAttributeName : UIFont.boldSystemFont(ofSize: 18)
]
Upvotes: 0
Reputation: 1664
Swift 4 Attributed text with multiple colors
extension NSMutableAttributedString
{
@discardableResult func DustyOrange(_ text: String, Fontsize : CGFloat) -> NSMutableAttributedString
{
let attrs: [NSAttributedStringKey: Any] = [.font: UIFont(name: "SFUIDisplay-Regular", size: Fontsize)!, NSAttributedStringKey.foregroundColor: UIColor(red: 242.0/255.0, green: 97.0/255.0, blue: 0.0/255.0, alpha: 1.0) ]
let boldString = NSMutableAttributedString(string:text, attributes: attrs)
append(boldString)
return self
}
@discardableResult func WarmGrey(_ text: String, Fontsize : CGFloat) -> NSMutableAttributedString {
let attrs: [NSAttributedStringKey: Any] = [.font: UIFont(name: "SFUIDisplay-Regular", size: Fontsize)!, NSAttributedStringKey.foregroundColor: UIColor(red: 152.0/255.0, green: 152.0/255.0, blue: 152.0/255.0, alpha: 1.0) ]
let boldString = NSMutableAttributedString(string:text, attributes: attrs)
append(boldString)
return self
}
}
Now you can Execute the function something like this to use as a globally
func FormattedString(Orange : String, WarmGrey : String ,fontsize : CGFloat) -> NSMutableAttributedString
{
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .left
paragraphStyle.lineSpacing = 1
paragraphStyle.paragraphSpacing = 1
let formattedString = NSMutableAttributedString()
formattedString
.DustyOrange(Orange, Fontsize: fontsize)
.WarmGrey(WarmGrey, Fontsize: fontsize )
formattedString.addAttributes([NSAttributedStringKey.paragraphStyle: paragraphStyle], range: NSRange(location: 0, length: formattedString.length))
return formattedString
}
You can use globalized function like this
yourLabelName.attributedText = FormattedString(Orange: "String with orange color", WarmGrey: " String with warm grey color.", fontsize: 11.5)
Attributed text with image
func AttributedTextwithImgaeSuffix(AttributeImage : UIImage , AttributedText : String , buttonBound : UIButton) -> NSMutableAttributedString
{
let fullString = NSMutableAttributedString(string: AttributedText + " ")
let image1Attachment = NSTextAttachment()
image1Attachment.bounds = CGRect(x: 0, y: ((buttonBound.titleLabel?.font.capHeight)! -
AttributeImage.size.height).rounded() / 2, width:
AttributeImage.size.width, height: AttributeImage.size.height)
image1Attachment.image = AttributeImage
let image1String = NSAttributedString(attachment: image1Attachment)
fullString.append(image1String)
fullString.append(NSAttributedString(string: ""))
return fullString
}
you can use "NSTextAttachment" with your button label like this.
yourUIButton.setAttributedTitle(AttributedTextwithImgaeSuffix(AttributeImage: desiredImage, AttributedText: "desired UIButton title", buttonBound: yourUIButton), for: .normal)
Upvotes: 0
Reputation: 7485
NSAttributedStringKey.strokeColor.rawValue
is of typeString
NSAttributedStringKey.strokeColor
is of typeNSAttributedStringKey
So its unable to convert String
to NSAttributedStringKey
.
You have to use like below:
let strokeTextAttributes: [NSAttributedStringKey : Any] = [
NSAttributedStringKey.strokeColor : UIColor.black,
NSAttributedStringKey.foregroundColor : UIColor.white,
NSAttributedStringKey.strokeWidth : -2.0,
NSAttributedStringKey.font : UIFont.boldSystemFont(ofSize: 18)
]
Upvotes: 1