Reputation: 295
I'm embedding an image in an NSAttributedString, and I want iOS to treat it as a character that is a part of the word before it, so that it doesn't get broken onto its own line. I read somewhere that is supposed to be the default behavior, but for the life of me I can't get it to work. Here's my code (I'm the inserting this attributed string as the title of a button):
var title = "This is an example string. Test testtt"
let titleTextString = NSMutableAttributedString(string: title)
let imageAttachment = NSTextAttachment()
imageAttachment.image = UIImage(named:"myIcon")
imageAttachment.bounds = CGRect(x: 0, y: 1.0, width: 14, height: 6)
let imageAttachmentString = NSMutableAttributedString(attachment: imageAttachment)
titleTextString.append(imageAttachmentString)
button.setAttributedTitle(titleTextString, for: .normal)
Here's an image of what it looks like:
As you can see, there is no whitespace at the end of the string. I am trying to get the label to consider the text attachment a normal non-whitespace character, and thus part of the word "testtt", which would then cause the "testtt" to be word-wrapped (words are otherwise correctly word-wrapped, and I've set word wrapping on both the label and in the paragraph style of the NSAttributedString).
Complicating this matter is that I found the existence of a non-breaking which solve the problem, but forces other parts of the string to be unnecessarily broken. If I append a non-breaking space to the end of the string:
var title = "This is an example string. Test testtt" + "\u{A0}"
I then get the correct breaking behavior, but for some reason the previous word is also unnecessarily broken:
Does anyone have any idea how to get this to behavior correctly (i.e., count the image as any other letter, rather than whitespace?)
Upvotes: 6
Views: 1713
Reputation: 4570
Set button title label text lineBreakMode
as .byWordWrapping
and textAlignment
as .center
to get the output as you aspect, See the following code.
let title = "This is an example string. Test testtt"
let titleTextString = NSMutableAttributedString(string: title)
let imageAttachment = NSTextAttachment()
imageAttachment.image = UIImage(named:"myIcon")
imageAttachment.bounds = CGRect(x: 0, y: 1.0, width: 14, height: 7)
let imageAttachmentString = NSMutableAttributedString(attachment: imageAttachment)
titleTextString.append(imageAttachmentString)
button.titleLabel?.lineBreakMode = .byWordWrapping
button.titleLabel?.textAlignment = .center
button.setAttributedTitle(titleTextString, for: .normal)
Upvotes: 0
Reputation: 977
You can accomplish that by adding a zero-width non-breaking space: \u{FEFF}
to the end of your original string.
var title = "This is an example string. Test testtt\u{FEFF}"
let titleTextString = NSMutableAttributedString(string: title)
let imageAttachment = NSTextAttachment()
imageAttachment.image = UIImage(named:"myIcon")
imageAttachment.bounds = CGRect(x: 0, y: 1.0, width: 14, height: 6)
let imageAttachmentString = NSMutableAttributedString(attachment: imageAttachment)
titleTextString.append(imageAttachmentString)
button.setAttributedTitle(titleTextString, for: .normal)
Credit to this SO question+answer In a UILabel, is it possible to force a line NOT to break in a certain place
EDIT:
To answer your question about wrong word wrapped. You can find the answer here. It's a new behavior for word wrapping introduced by Apple.
Upvotes: 4