У меня есть пользовательский класс кнопок в UIView, который я бы хотел добавить в массив, чтобы они были легко доступны. Есть ли способ получить все подъязыки определенного класса и добавить его в массив в Swift?
Swift: получить все подвидности определенного типа и добавить к массиву
Ответ 1
Функция filter
, использующая оператор is
, может фильтровать элементы определенного класса.
let myViews = view.subviews.filter{$0 is MyButtonClass}
MyButtonClass
- это настраиваемый класс для фильтрации.
Ответ 2
Здесь вы идете
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)
Ответ 3
Чтобы сделать это рекурсивно (например, выборка всех представлений подзаголовка), вы можете использовать эту общую функцию:
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
}
Чтобы получить все UILabel в иерархии представлений, просто выполните следующее:
let allLabels : [UILabel] = getSubviewsOf(view: theView)
Ответ 4
Я не могу проверить это сейчас, но это должно работать в Swift 2:
view.subviews.flatMap{ $0 as? YourView }
Возвращает массив YourView
Здесь приведен пример типичного примера для получения счета:
countDots = allDots!.view.subviews.flatMap{$0 as? Dot}.count
Ответ 5
Если вы хотите обновить/получить доступ к этим конкретным подзаголовкам, используйте это,
for (index,button) in (view.subviews.filter{$0 is UIButton}).enumerated(){
button.isHidden = false
}
Ответ 6
В Swift 4.1 вы можете использовать новый compactMap (flatMap теперь устарел): https://developer.apple.com/documentation/swift/sequence/2950916-compactmap (см. Примеры внутри)
В вашем случае вы можете использовать:
let buttons:[UIButton] = stackView.subviews.compactMap{ $0 as? UIButton }
И вы можете выполнить действия для всех кнопок, используя карту:
let _ = stackView.subviews.compactMap{ $0 as? UIButton }.map { $0.isSelected = false }
Ответ 7
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)
Ответ 8
В этом случае, я думаю, мы могли бы использовать синтаксис Swift first.where
, который более эффективен, чем filter.count
, filter.isEmpty
.
Потому что, когда мы используем filter
, он создаст базовый массив, поэтому неэффективен, предположим, что у нас есть большая коллекция.
Итак, просто проверьте, содержит ли коллекция subViews
определенный тип класса, мы можем использовать этот
let containsBannerViewKind = view.subviews.first(where: { $0 is BannerView }) != nil
который эквивалентен: найдите мне первое совпадение с классом BannerView в этом представлении subViews collection. Поэтому, если это так, мы можем выполнить нашу дальнейшую логику.
Ссылка: https://github.com/realm/SwiftLint/blob/master/Rules.md#first-where
Ответ 9
UIView имеет свойство с именем subViews
, вы можете увидеть API.
Ответ 10
Позвольте мне опубликовать мой вариант этого) но это, находит первый из 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
}
}
Ответ 11
Так что многие ответы здесь излишне многословны или недостаточно общие. Вот как получить все подпредставления вида на любой глубине, которые относятся к любому желаемому классу:
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)