24

I have the following code for a Table View Cell in Swift

let rcap = cell.viewWithTag(613) as! UILabel
rcap.text = "Capacity: \(room.capacity)  "  // I added space at the end

The space characters at the end of the string, are removed when shown on screen.

If I add space characters at the beginning of the string there is no issue.

At the moment I am using this 'full stop' hack, but it is not good enough:

rcap.text = "Capacity: \(room.capacity)   ."  

Any ideas?

I also tried:

rcap.text = "Capacity: \(room.capacity)  " + " "
pkamb
  • 33,281
  • 23
  • 160
  • 191
Greg Peckory
  • 7,700
  • 21
  • 67
  • 114
  • That's nice. I would like more control over the amount of spaces, but that is a nice approach for the moment ! – Greg Peckory Jul 21 '15 at 09:11
  • ok...i think `\t` works but with small amount of space – Bhavin Bhadani Jul 21 '15 at 09:14
  • 2
    It would be interesting to know why the trailing space is important. Perhaps there is a different solution to your problem. – Martin R Jul 21 '15 at 09:23
  • I have a label that is aligned to right. But I don't want the text starting at the very right of the screen. I could add some constraints to the label and that would work, but I'm just surprised there is no option for space at the end – Greg Peckory Jul 21 '15 at 09:34
  • Any update on this for Swift 5? I have a problem where adding two spaces on the end of string is the most elegant solution. I tried adjusting constraints, but in my situation, adjusting constraints gets very messy. – Ryan Jun 30 '19 at 02:22
  • 1
    @Ryan , Martin's "awesome trick" DOES IN FACT WORK today, 2020. This is absolutely essential when working with monospaced fonts. – Fattie Jan 19 '20 at 18:40
  • @GregPeckory regarding your old question here, this is a critical and awesome question for anyone obsessed with layout details, so, I have added a fatass bounty! cheers – Fattie Jan 19 '20 at 19:04
  • You can use UIButton with userInteractioinEnabled as false. And use titleInsets property to achieve this. – Vinoth Feb 25 '21 at 03:20

6 Answers6

44

Adding a constraint to the label seems like the better solution to me. It allows you to define a well-defined distance between the label and the margin of the table view cell. The width of a space is dependent on the font and might even change if the text in the label is shrunk, causing non-aligned texts in the table view.

Having said that, you can prevent the trailing space from being removed by appending a "ZERO WIDTH NON-JOINER" character (U+200C):

rcap.text = "Capacity: \(room.capacity)  \u{200c}"

But I consider that more as a "trick" than the proper solution to the problem.

Update: It seems that this "trick" does not work any more in iOS 10, so a layout constraint should be used instead, as initially suggested.

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • @onemoreanimal: How does it "not work"? Does it not compile? Does it produce an unexpected result? – Martin R Apr 30 '17 at 20:58
  • It compiles and runs but the compiler still strips the trailing whitespace from the UILabel before the special character – onemoreanimal May 01 '17 at 21:50
  • @onemoreanimal: It does not work in iOS 10 anymore (independent of the Swift version). I have updated the answer accordingly. Thanks for the feedback! – Martin R May 02 '17 at 07:09
  • Space + ZERO WIDTH NON-JOINER + space `" \u{200c} "` is worked at iOS 10.3. It seems like one space. – najeira Jun 12 '17 at 04:12
  • @MartinR , strangely enough this seems to **work perfectly** today, 2020, in current Xcode / iOS. BTW regarding your question up top, it's almost essential to be able to do this when doing something with monospace fonts. (The only other solution I know is to annoyingly make a minimum width (ie in intrinsicContentSize / textRect) based on a phantom example string, which is a real mess.) Again unless something weird is going on, ***this currently works perfectly - and thanks for the amazing tip!*** – Fattie Jan 19 '20 at 18:44
  • 1
    Unicode Character 'INVISIBLE SEPARATOR' (U+2063) should work as well and it has 0 width too. – user3441734 Jan 22 '20 at 21:32
  • 1
    @user3441734 , that is a HUGE tip, you should put it in as an answer. – Fattie Jan 23 '20 at 01:03
4

For 2020

This issue is critical when working with monospaced fonts and doing layout, such as, say, user codes which may have alignment spaces at the end in monospace.

\u{200c} does seem to work perfectly:

Please note that the solution of @MartinR does in fact work perfectly, today, 2020 A.D., iOS 13, Xcode 11.

.text = "FATTIE KODE " + reservation + reservation.neededTrailingSpaces + \u{200c}"

enter image description here

.text = "FATTIE KODE " + reservation + reservation.neededTrailingSpaces + \u{200c}"

enter image description here

.text = "FATTIE KODE " + reservation + reservation.neededTrailingSpaces + \u{200c}"

enter image description here

You can now absolutely normally set font sizes, etc etc. and it all works properly.


Bonus code sample!

Here's a simple UILabel that pads it out, so you need do nothing else:

class PaddyLabel: UILabel {

// pad always to 20 characters...

override var text: String? {
        get {
            return super.text
        }
        set {
            if newValue == nil {
                super.text = nil
                return
            }
            var t = newValue!
            while t.count < 20 { t += " " }
            t += "\u{200c}"
            super.text = t
        }
    }

So in the above three yellow examples, you would just do this

.text = "FATTIE KODE " + reservation

and not have to bother adding the needed spaces manually.


Note that even if you are not using monospace fonts, a typical real-world use case is when you want to "pile together" UILabels - imagine them being, say, one word each - and have the absolutely correct space between them regardless of font size etc, that is to say as if it's just the one sentence in the one UILabel.

The only way to actually do that is to have UILabel "actually include the space".


If it does not work in a future iOS...

Perhaps this will (again?) break in a future iOS.

The only other solution I know is this. To begin with, it's ridiculously hard to just add padding to a UILabel. It is explained here:

Adding padding manually to a UILabel?

How to actually reliably add damned padding to a UILabel

In fact, using a similar technique, it would be possible to force the extra width on one end using intrinsicContentSize , drawText and textRect. To know how much width to add, you would have to calculate that using a phantom example text, with the number of characters in question. Doing that calculation would call for the usual annoying techniques for calculating likely text rendering size. But because that sucks, fortunately we can use the amazing tip of @MartinR (as usual!)

Community
  • 1
  • 1
Fattie
  • 27,874
  • 70
  • 431
  • 719
0

I have created custom class for UILabel, take a look:

import UIKit

@IBDesignable class CustomLable: UILabel {
    @IBInspectable var topInset: CGFloat = 5.0
    @IBInspectable var bottomInset: CGFloat = 5.0
    @IBInspectable var leftInset: CGFloat = 7.0
    @IBInspectable var rightInset: CGFloat = 7.0

    override func drawText(in rect: CGRect) {
        let insets = UIEdgeInsets.init(top: topInset, left: leftInset, bottom: bottomInset, right: rightInset)
        super.drawText(in: rect.inset(by: insets))
    }

    override var intrinsicContentSize: CGSize {
        let size = super.intrinsicContentSize
        return CGSize(width: size.width + leftInset + rightInset,
                      height: size.height + topInset + bottomInset)

    }

}

You can than assign a class to UILabel from Storyboard and provide space you need.

  • Please note, this question is about the **character " " space** - not about "adding space" (padding). – Fattie Jan 23 '20 at 11:00
  • Also for anyone googling here, if you are adding padding, this is not exactly correct. It's actually really tricky to add padding in a UILabel! A full examination of this issue: https://stackoverflow.com/a/58876988/294884 – Fattie Jan 23 '20 at 11:01
0

Try putting zero-width space instead of the period. It can be written using left Alt and 0173 on numeric keyboard. Or you can copy it here and delete the quotes: "­"

So your code for setting the text will look like this (with the zero-width space at the end):
rcap.text = "Capacity: \(room.capacity) ­"
Non-breaking space (\u{00a0}) should work too and its usage is as \u{200c}'s in Martin's and Fattie's answer

David Buck
  • 3,752
  • 35
  • 31
  • 35
Encyklopedie
  • 111
  • 1
  • 6
0

I found a suprising trick. Spaces are removed at the end, except if they are inside an interpolated string.

So for instance, instead of writing

let aLine = "Hello" + "  "

I write (a bit convoluted)

let aLine = "Hello" + "\("  ")"

Then the spaces are kept at the end. But you may need to adjust the number of spaces to get it as expected.

If that may help…

claude31
  • 874
  • 6
  • 8
-3
rcap.text = String.localizedStringWithFormat("Capacity: %@ ", rrom.capacity)

try above code it may works

Ramkumar chintala
  • 958
  • 11
  • 24