UIViewにカスタムクラスのボタンがあり、それらを簡単にアクセスできるように配列に追加します。特定のクラスのすべてのサブビューを取得し、それをSwiftの配列に追加する方法はありますか?
filter
演算子を使用するis
関数は、特定のクラスのアイテムをフィルターできます。
let myViews = view.subviews.filter{$0 is MyButtonClass}
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)
これを再帰的に行う(つまり、すべてのサブビューのビューもフェッチする)には、次の汎用関数を使用できます。
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)
私は今それをテストすることはできませんが、これはSwift 2:
view.subviews.flatMap{ $0 as? YourView }
YourView
の配列を返します
カウントを取得するためのテスト済みの典型的な例を次に示します。
countDots = allDots!.view.subviews.flatMap{$0 as? Dot}.count
これらの特定のサブビューを更新/アクセスする場合は、これを使用します。
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)
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 }
この場合、first.where
、filter.count
よりも効率的なSwiftのfilter.isEmpty
構文を使用できると思います。
filter
を使用すると、基礎となる配列が作成されるため、効果的ではないため、大きなコレクションがあると想像してください。
ビューのsubViews
コレクションに特定の種類のクラスが含まれているかどうかを確認するだけで、これを使用できます
let containsBannerViewKind = view.subviews.first(where: { $0 is BannerView }) != nil
これは、このビューのsubViewsコレクションでBannerViewクラスに最初に一致するものを見つけます。したがって、これが当てはまる場合は、さらにロジックを実行できます。
リファレンス: https://github.com/realm/SwiftLint/blob/master/Rules.md#first-where
UIViewにはsubViews
という名前のプロパティがあり、APIを見ることができます。
これの私のバリエーションを投稿しましょう)しかし、これは、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
}
}