9

I am going through the Stanford Winter 2015 Swift/iOS course and while doing the assignments I run into a behavior I'd like to change.

I use Autolayout as described in the videos (making the display pin to leading and trailing view edges) and the Calculator app "Display" UILabel is fine with an initial value of 0 and whenever the value used to set it (a String) is non-nil and non "".

If it is either nil or "", the entire UILabel disappears. What I am trying to do is to "clear" the display whenever there is no value to display or an incorrect calculation resulted in nil.

Any tips on who to deal with this in general? "Clearing" a UILabel without changing it's on-screen dimensions?


Edit (thanks Rob) The UILabel has the following constraints 1. Option-click drag-left to containing UIView, selected "leading" something (on commute to work can't check yet for exact wording. 2. Same method as (1) except that the drag is to the right edge and selecting "trailing" 3. Option click-drag up to top of view, select "vertical" menu option. 4. Same as (3) except that drag is to a UIButton underneath the UILabel on the GUI.

With those settings, the label when it contains a number is always visible and (if understand, will color it to verify) stretches across the screen even if the text doesn't.

The layout looks correct in profile and landscape as long as content of UILabel is not empty. If empty, it seems to "shrink to fit" so much that the buttons below get moved up towards the top.

I'm a C++ dev since mid 90s but I have little UI experience and no more than a couple weeks experience in iOS/Swift development.

Thanks!

Varsuuk
  • 115
  • 1
  • 10
  • Edit your question to describe the constraints you have set on your label view to control its position and size. – rob mayoff Oct 28 '15 at 04:39
  • Have you tried calling `label.sizeToFit()`? – Pranav Oct 28 '15 at 04:51
  • Have you tried making an if statement that returns: " " (clearing the label) if the countDown timer == 0? @Varsuuk – Lukesivi Oct 28 '15 at 13:29
  • Not sure what the "countDown timer == 0?" references ;) but I did settle on the very "unappealing to my developer sensitivities" workaround of setting the UILabel to " " (1 space) whenever the backing Double? property returned nil. – Varsuuk Oct 28 '15 at 21:44
  • Is UILabel inside UIStackView? – andy shih Aug 18 '16 at 07:13

2 Answers2

3

You can always give the UILabel a min width and min height or constraints that holds the left and right side of the label. That should keep the label from changing it's dimensions to zero.

Moriya
  • 7,750
  • 3
  • 35
  • 53
  • Thanks, I will check this when at the Mac, but is there a way to make the min width controlled by iOS to be the view width? I had believed that was what I was doing when option drag-clicked to left and right edges from control but I am new to this. Perhaps it IS the full width but maybe it's the height, as you mentioned, that might have shrunk - I'll color the UILabel differently from view to get more info. – Varsuuk Oct 28 '15 at 13:27
  • I think what you need to do is to give it a minimum height as well then. – Moriya Oct 28 '15 at 13:29
  • Thanks @animal, was thinking that but typing on the iPad with my cranky thumbs made me hit enter one line too soon in prior comment. Will check and update. – Varsuuk Oct 28 '15 at 13:30
  • I updated the code to set the UILable opaque and it does, in fact, go from filling the whole line across in black when start and have valid values in the UILabel to nothing when it is nil or "".\n Trying to look at how to set the "min heigh/widtht" vs what I did of setting the autolayout constraints via option-drag. I may need to try tonight as work was too busy to look at these things beyond the recent updates. Thanks! – Varsuuk Oct 28 '15 at 21:46
  • Perhaps this can help: https://developer.apple.com/library/ios/recipes/xcode_help-IB_auto_layout/chapters/EditingConstraintAttributesintheAttributesInspector.html – Moriya Oct 29 '15 at 02:47
  • Thanks again for the link (yes, I am that new with iOS development.) I was able to get the look I wanted by setting the UILabel size via a small Option-Drag-Up within the UILabel itself which popped up a choice to set the Height (I will read on link for alternate ways to add such a contraint.) I accepted the supplied value and after some other non-important to here adjustments, it worked as well as text=" " – Varsuuk Oct 29 '15 at 17:15
  • --- The only concern I have is if accepting that default height size is a "bad thing" if the device it runs on changes. I tried it on iPadPro sim and boy was print small - but then so were my buttons. Again, this is early on in the iTunesU class so we will probably learn about adjusting fonts based on some indication (possibly size classes?) of what the host is. Anyhow, your "set height constraint" once I finally puzzled out how to do what you suggested, worked fine. Thanks @Animal. – Varsuuk Oct 29 '15 at 17:17
1

Use a custom UILabel class assigned in Interface Builder >> Identity inspector >> Custom Class >> Class to override UILabel intrinsic content size.

No need to create any superfluous auto-layout constraints.

Swift:

class UILabelNonCompressible: UILabel
{
    private static let NonCompressibleInvisibleContent = " "

    override var intrinsicContentSize: CGSize
    {
        if /* zero-width */ text == nil ? true : text!.isEmpty
        {
            // prefer mirror-and-calculate over modify-calculate-restore due to KVO
            let doppelganger = createCopy()

            // calculate for any non-zero -height content
            doppelganger.text = UILabelNonCompressible.NonCompressibleInvisibleContent

            // override
            return doppelganger.intrinsicContentSize
        }
        else
        {
            return super.intrinsicContentSize
        }
    }
}

You will also need "How do copy for UILabel?":

extension UILabel
{
    func createCopy() -> UILabel
    {
        let archivedData = NSKeyedArchiver.archivedData(withRootObject: self)
        return NSKeyedUnarchiver.unarchiveObject(with: archivedData) as! UILabel
    }
}
Gary
  • 815
  • 10
  • 16