0

The Story:

So I was looking over ways on how to hide a UIPickerView's selection indicator, and I saw some SO threads that had a workaround.

However, when I tried using that in Xcode 9 (beta 4) with Swift 4, I found that it didn't work. Upon further inspection I realized that whenever I called myPickerView.subviews, I got a count of 0. Now this is weird as it apparently worked before as the other threads suggest.

I checked using the debug view hierarchy tool, and it seems that the subview structure is unchanged, with 3 subviews as older threads seem to have as well. But for some reason I can't access them. The incredible part though, is if I set the language to Swift 3.2 and run the same project on iOS 9.0 I still get the same error. So I can't really tell when or where the change seems to originate. I unfortunately don't have an older version of xcode to test on anymore.

This same thing seems to happen with multiple UIKit elements though, but not all of them. A full list is at the end of this post. I've tried to be as comprehensive as possible, feel free to let me know if I missed anything.

I know the correct way to solve this would be to make my own UIScrollView and customize it, but for future use and for the rest of the elements, anyone have any idea if there's a workaround to what already was a workaround?

Elements that still have Subviews:

  • UISwitch : 1 Subview
  • UITextView : 1 Subview
  • UIDatePicker : 1 Subview
  • UITableView : 1 Subview
  • UISearchBar : 1 Subview
  • UIProgressView : 2 Subviews
  • UIStepper : 3 Subviews

Elements that have no Subviews:

  • UISegmentedControl
  • UIPickerView
  • UITextField
  • UISlider
  • UIPageControl

Source Code used to get these results:

    let tableView        = UITableView()
    let pickerViewHere   = UIPickerView()
    let segmentedControl = UISegmentedControl()
    let textField        = UITextField()
    let slider           = UISlider()
    let switchUI         = UISwitch()
    let progressView     = UIProgressView()
    let pageControl      = UIPageControl()
    let stepper          = UIStepper()
    let textView         = UITextView()
    let datePicker       = UIDatePicker()
    let searchBar        = UISearchBar()
    
    
    print("switchUI has: (\(switchUI.subviews.count)) subviews")
    print("progressView has: (\(progressView.subviews.count)) subviews")
    print("stepper has: (\(stepper.subviews.count)) subviews")
    print("textView has: (\(textView.subviews.count)) subviews")
    print("datePicker has: (\(datePicker.subviews.count)) subviews")
    print("tableView has: (\(tableView.subviews.count)) subviews")
    print("segmentedControl has: (\(segmentedControl.subviews.count)) subviews")
    print("pickerViewHERE has: (\(pickerViewHere.subviews.count)) subviews")
    print("pickerView has: (\(pickerView.subviews.count)) subviews")
    print("searchBar has: (\(searchBar.subviews.count)) subviews")
    print("textField has: (\(textField.subviews.count)) subviews")
    print("slider has: (\(slider.subviews.count)) subviews")
    print("pageControl has: (\(pageControl.subviews.count)) subviews")
Community
  • 1
  • 1
JoeVictor
  • 1,806
  • 1
  • 17
  • 38
  • If you want an older version of xcode you can just download it from the apple's developer portal. they are all there. However, what you could probably just do is change the deployment target to iOS 10, since that way you won't be using the new APIs – Pochi Aug 04 '17 at 02:41
  • The problem is I don't have storage on my computer, that's why I erased my (stable) version of Xcode 8! – JoeVictor Aug 04 '17 at 11:55

1 Answers1

1

Apparently, in iOS 11, UIPickerView creates its subviews in its layoutSubviews method. Presumably the other views also create their subviews lazily.

Test code:

import UIKit

class ViewController: UIViewController {
    let pickerView = MyPickerView()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(pickerView)
        pickerView.frame = view.bounds
    }
}

class MyPickerView: UIPickerView {
    override func layoutSubviews() {
        print("before layoutSubviews: \(subviews.count)")
        super.layoutSubviews()
        print("after layoutSubviews: \(subviews.count)")
    }
}

Output:

before layoutSubviews: 0
after layoutSubviews: 3
before layoutSubviews: 3
after layoutSubviews: 3
before layoutSubviews: 3
after layoutSubviews: 3
rob mayoff
  • 375,296
  • 67
  • 796
  • 848
  • Thanks! Any clue why if I run this on iOS 9.0 on the simulator I get the same results? Is the SDK that is compiled that changed or what? – JoeVictor Aug 04 '17 at 11:56
  • Also, as a note to rob's answer, if you call layoutSubviews() in the viewDidLoad, and you've created your UIPickerView in the storyboard, nothing happens. You have to wait until addSubview() is called either by the storyboard or manually – JoeVictor Aug 04 '17 at 14:25