我有一个在UIView中的自定义按钮类,我希望将它们添加到数组中以便轻松访问。在Swift中,是否有一种方法可以获取特定类别的所有子视图并将其添加到数组中?
使用is
运算符的filter
函数可以过滤特定类别的项目。
let myViews = view.subviews.filter{$0 is MyButtonClass}
MyButtonClass
是要过滤的自定义类。
要将视图过滤并将其转换为自定义类型,请使用 compactMap
。
let myViews = view.subviews.compactMap{$0 as? MyButtonClass}
这里是您需要的内容。
extension UIView {
/** This is the function to get subViews of a view of a particular type
*/
func subViews<T : UIView>(type : T.Type) -> [T]{
var all = [T]()
for view in self.subviews {
if let aView = view as? T{
all.append(aView)
}
}
return all
}
/** This is a function to get subViews of a particular type from view recursively. It would look recursively in all subviews and return back the subviews of the type T */
func allSubViewsOf<T : UIView>(type : T.Type) -> [T]{
var all = [T]()
func getSubview(view: UIView) {
if let aView = view as? T{
all.append(aView)
}
guard view.subviews.count>0 else { return }
view.subviews.forEach{ getSubview(view: $0) }
}
getSubview(view: self)
return all
}
}
let allSubviews = view.allSubViewsOf(type: UIView.self)
let allLabels = view.allSubViewsOf(type: UILabel.self)
view.subviews.forEach(getSubview)
- Leo Dabus这里有很多回答过度冗长或者不够普遍。以下是获取任何深度的视图中,所有想要的类别的所有子视图的方法:
extension UIView {
func subviews<T:UIView>(ofType WhatType:T.Type) -> [T] {
var result = self.subviews.compactMap {$0 as? T}
for sub in self.subviews {
result.append(contentsOf: sub.subviews(ofType:WhatType))
}
return result
}
}
使用方法:
let arr = myView.subviews(ofType: MyButtonClass.self)
.subviews
中。我想不出任何平台、API等在使用或口语中使用subviews来表示“grand”-subviews以及subviews的情况。我只是会稍微不同地命名它(实际上,我不知道最常用的表达方式是什么,也许是nestedSubviews#ofType,或者是subsubviews#ofType,我不知道)。 - undefinedrecursing
作为参数。所以你可以选择是否递归。我建议你也这样做。 - undefined要递归地执行此操作(即获取所有子视图的视图),可以使用以下通用函数:
private func getSubviewsOf<T : UIView>(view:UIView) -> [T] {
var subviews = [T]()
for subview in view.subviews {
subviews += getSubviewsOf(view: subview) as [T]
if let subview = subview as? T {
subviews.append(subview)
}
}
return subviews
}
let allLabels : [UILabel] = getSubviewsOf(view: theView)
我现在无法测试,但这应该适用于Swift 2:
view.subviews.flatMap{ $0 as? YourView }
该函数返回一个YourView
数组。
这是一个经过测试的典型示例,用于获取计数:
countDots = allDots!.view.subviews.flatMap{$0 as? Dot}.count
let buttons:[UIButton] = stackView.subviews.compactMap{ $0 as? UIButton }
你可以使用map来执行所有按钮的操作:
let _ = stackView.subviews.compactMap{ $0 as? UIButton }.map { $0.isSelected = false }
for (index,button) in (view.subviews.filter{$0 is UIButton}).enumerated(){
button.isHidden = false
}
func allSubViews(views: [UIView]) {
for view in views {
if let tf = view as? UITextField {
// Do Something
}
self.allSubViews(views: view.subviews)
}
}
self.allSubViews(views: self.view.subviews)
func
应该返回一个视图数组,因为这是提问者所要求的;而且为什么要使用 UITextField
?MyCustomButton
更加合适。 - dirkgrotenfirst.where
语法,它比filter.count
和filter.isEmpty
更有效率。filter
时,它会创建一个底层数组,因此不太有效,想象一下我们有一个大的集合。subViews
集合是否包含特定类型的类,我们就可以使用这个方法。let containsBannerViewKind = view.subviews.first(where: { $0 is BannerView }) != nil
让我发布我的变体) 但是这个找到T的第一个
extension UIView {
func firstSubView<T: UIView>(ofType type: T.Type) -> T? {
var resultView: T?
for view in subviews {
if let view = view as? T {
resultView = view
break
}
else {
if let foundView = view.firstSubView(ofType: T.self) {
resultView = foundView
break
}
}
}
return resultView
}
}