在 Xcode 9 / Swift 4 中不再可以访问原生 UIKit 元素的子视图?
Native UIKit elements' subviews are no longer accessible in Xcode 9 / Swift 4?
故事:
所以我正在研究如何隐藏 UIPickerView
的选择指示器,我看到 some SO threads 有解决方法。
然而,当我尝试在 Xcode 9(测试版 4)和 Swift 4 中使用它时,我发现它不起作用。经过进一步检查,我意识到每当我调用 myPickerView.subviews
时,我得到的计数为 0。现在这很奇怪,因为它显然像其他线程所建议的那样起作用。
我使用调试视图层次结构工具进行了检查,子视图结构似乎没有变化,older threads 似乎也有 3 个子视图。但出于某种原因,我无法访问它们。令人难以置信的是,如果我将语言设置为 Swift 3.2 和 运行 iOS 9.0 上的同一项目,我仍然会遇到相同的错误。所以我真的无法确定变化似乎起源于何时何地。不幸的是,我没有旧版本的 xcode 可以测试了。
同样的事情似乎发生在多个 UIKit 元素上,但不是全部。完整列表位于此 post 的末尾。我尽量做到全面,如有遗漏请随时告诉我。
我知道解决这个问题的正确方法是制作我自己的 UIScrollView
并自定义它,但是为了将来使用和其余元素,任何人都知道是否有解决方法已经是解决方法了吗?
仍有子视图的元素:
UISwitch
:1 个子视图
UITextView
:1 个子视图
UIDatePicker
:1 个子视图
UITableView
:1 个子视图
UISearchBar
:1 个子视图
UIProgressView
:2 个子视图
UIStepper
:3 个子视图
没有子视图的元素:
UISegmentedControl
UIPickerView
UITextField
UISlider
UIPageControl
用于获取这些结果的源代码:
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")
显然,在 iOS 11 中,UIPickerView
在其 layoutSubviews
方法中创建其子视图。大概其他视图也懒惰地创建它们的子视图。
测试代码:
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)")
}
}
输出:
before layoutSubviews: 0
after layoutSubviews: 3
before layoutSubviews: 3
after layoutSubviews: 3
before layoutSubviews: 3
after layoutSubviews: 3
故事:
所以我正在研究如何隐藏 UIPickerView
的选择指示器,我看到 some SO threads 有解决方法。
然而,当我尝试在 Xcode 9(测试版 4)和 Swift 4 中使用它时,我发现它不起作用。经过进一步检查,我意识到每当我调用 myPickerView.subviews
时,我得到的计数为 0。现在这很奇怪,因为它显然像其他线程所建议的那样起作用。
我使用调试视图层次结构工具进行了检查,子视图结构似乎没有变化,older threads 似乎也有 3 个子视图。但出于某种原因,我无法访问它们。令人难以置信的是,如果我将语言设置为 Swift 3.2 和 运行 iOS 9.0 上的同一项目,我仍然会遇到相同的错误。所以我真的无法确定变化似乎起源于何时何地。不幸的是,我没有旧版本的 xcode 可以测试了。
同样的事情似乎发生在多个 UIKit 元素上,但不是全部。完整列表位于此 post 的末尾。我尽量做到全面,如有遗漏请随时告诉我。
我知道解决这个问题的正确方法是制作我自己的 UIScrollView
并自定义它,但是为了将来使用和其余元素,任何人都知道是否有解决方法已经是解决方法了吗?
仍有子视图的元素:
UISwitch
:1 个子视图UITextView
:1 个子视图UIDatePicker
:1 个子视图UITableView
:1 个子视图UISearchBar
:1 个子视图UIProgressView
:2 个子视图UIStepper
:3 个子视图
没有子视图的元素:
UISegmentedControl
UIPickerView
UITextField
UISlider
UIPageControl
用于获取这些结果的源代码:
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")
显然,在 iOS 11 中,UIPickerView
在其 layoutSubviews
方法中创建其子视图。大概其他视图也懒惰地创建它们的子视图。
测试代码:
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)")
}
}
输出:
before layoutSubviews: 0
after layoutSubviews: 3
before layoutSubviews: 3
after layoutSubviews: 3
before layoutSubviews: 3
after layoutSubviews: 3