92

内のすべてのサブビューを一覧表示したいUIViewController。を試しself.view.subviewsましたが、すべてのサブビューがリストされているわけではありません。たとえば、 のサブビューがUITableViewCell見つかりません。何か案が?

4

22 に答える 22

175

サブビューを再帰的に繰り返す必要があります。

- (void)listSubviewsOfView:(UIView *)view {
    
    // Get the subviews of the view
    NSArray *subviews = [view subviews];

    for (UIView *subview in subviews) {
        
        // Do what you want to do with the subview
        NSLog(@"%@", subview);

        // List the subviews of subview
        [self listSubviewsOfView:subview];
    }
}
于 2011-08-30T13:38:02.450 に答える
35

ビュー階層をダンプする xcode/gdb 組み込みの方法は便利です -- http://developer.apple.com/library/ios/#technotes/tn2239/_index.htmlによる recursiveDescription

役立つと思われる、より完全なビュー階層を出力します。

> po [_myToolbar recursiveDescription]

<UIToolbarButton: 0xd866040; frame = (152 0; 15 44); opaque = NO; layer = <CALayer: 0xd864230>>
   | <UISwappableImageView: 0xd8660f0; frame = (0 0; 0 0); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0xd86a160>>
于 2012-01-22T17:00:27.790 に答える
13

再帰的に印刷する必要があります。このメソッドは、ビューの深さに基づいてタブも作成します

-(void) printAllChildrenOfView:(UIView*) node depth:(int) d
{
    //Tabs are just for formatting
    NSString *tabs = @"";
    for (int i = 0; i < d; i++)
    {
        tabs = [tabs stringByAppendingFormat:@"\t"];
    }

    NSLog(@"%@%@", tabs, node);

    d++; //Increment the depth
    for (UIView *child in node.subviews)
    {
        [self printAllChildrenOfView:child depth:d];
    }

}
于 2011-08-30T13:53:18.953 に答える
13

スイフト版はこちら

 func listSubviewsOfView(view:UIView){

    // Get the subviews of the view
    var subviews = view.subviews

    // Return if there are no subviews
    if subviews.count == 0 {
        return
    }

    for subview : AnyObject in subviews{

        // Do what you want to do with the subview
        println(subview)

        // List the subviews of subview
        listSubviewsOfView(subview as UIView)
    }
}
于 2014-06-16T13:06:37.553 に答える
7

私はパーティーに少し遅れていますが、もう少し一般的な解決策です:

@implementation UIView (childViews)

- (NSArray*) allSubviews {
    __block NSArray* allSubviews = [NSArray arrayWithObject:self];

    [self.subviews enumerateObjectsUsingBlock:^( UIView* view, NSUInteger idx, BOOL*stop) {
        allSubviews = [allSubviews arrayByAddingObjectsFromArray:[view allSubviews]];
                   }];
        return allSubviews;
    }

@end
于 2012-07-29T15:30:35.557 に答える
5

私はこのように使用します:

NSLog(@"%@", [self.view subviews]);

UIViewControllerで。

于 2012-09-18T07:56:05.687 に答える
2

以前に投稿された回答に触発された、ビューコントローラによって保持されているすべてのビューを一覧表示するカテゴリを作成しました。

@interface UIView (ListSubviewHierarchy)
- (NSString *)listOfSubviews;
@end

@implementation UIView (ListSubviewHierarchy)
- (NSInteger)depth
{
    NSInteger depth = 0;
    if ([self superview]) {
        deepth = [[self superview] depth] + 1;
    }
    return depth;
}

- (NSString *)listOfSubviews
{
    NSString * indent = @"";
    NSInteger depth = [self depth];

    for (int counter = 0; counter < depth; counter ++) {
        indent = [indent stringByAppendingString:@"  "];
    }

    __block NSString * listOfSubviews = [NSString stringWithFormat:@"\n%@%@", indent, [self description];

    if ([self.subviews count] > 0) {
        [self.subviews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
            UIView * subview = obj;
            listOfSubviews = [listOfSubviews stringByAppendingFormat:@"%@", [subview listOfSubviews]];
        }];
    }
    return listOfSubviews;
}
@end

ビューコントローラによって保持されているすべてのビューを一覧表示するには、ビューコントローラ自体NSLog("%@",[self listOfSubviews])を意味します。self効率的ではありませんが。

さらに、同じことを行うために使用することができNSLog(@"\n%@", [(id)self.view performSelector:@selector(recursiveDescription)]);、私の実装よりも効率的だと思います。

于 2012-11-10T18:10:48.960 に答える
2

UITableViewCell のサブビューが出力されない理由は、最上位のすべてのサブビューを出力する必要があるためです。セルのサブビューは、ビューの直接のサブビューではありません。

isKindOfClass:UITableViewCell のサブビューを取得するには、印刷ループで( を使用して) UITableViewCell に属するサブビューを特定し、そのサブビューをループする必要があります。

編集: Easy UIView Debuggingに関するこのブログ投稿が役立つ可能性があります

于 2011-08-30T13:30:08.520 に答える
1

スイフト2.0対応

ここでは、ジェネリック ビューのすべてのサブビューを取得するための再帰的な方法を示します。

extension UIView {
  func subviewsList() -> [UIView] {
      var subviews = self.subviews
      if subviews.count == 0 {
          return subviews + []
      }
      for v in subviews {
         subviews += v.listSubviewsOfView()
      }
      return subviews
  }
}

したがって、次の方法でどこでも呼び出すことができます。

let view = FooController.view
let subviews = view.subviewsList()
于 2015-10-09T16:08:29.330 に答える
1

次のような派手な配列のトリックを試すことができます。

[self.view.subviews makeObjectsPerformSelector: @selector(printAllChildrenOfView)];

わずか 1 行のコードです。もちろん、メソッドを調整してprintAllChildrenOfView、パラメーターを取らないようにするか、新しいメソッドを作成する必要がある場合があります。

于 2011-08-30T14:15:08.780 に答える
1

これはこの回答の書き直しです:

すべてのサブビューを印刷するオブジェクトへのポインター/参照を最初に取得する必要があります。サブビューからオブジェクトにアクセスすると、そのオブジェクトを簡単に見つけることができる場合があります。のようにpo someSubview.superview。これにより、次のような結果が得られます。

Optional<UIView>
  ▿ some : <FacebookApp.WhatsNewView: 0x7f91747c71f0; frame = (30 50; 354 636); clipsToBounds = YES; layer = <CALayer: 0x6100002370e0>>
  • FaceBookApp はアプリ名です
  • WhatsNewView はあなたのタイプですsuperview
  • 0x7f91747c71f0スーパービューへのポインタです。

superView を印刷するには、ブレークポイントを使用する必要があります。


このステップを実行するには、[デバッグ階層の表示] をクリックするだけです。ブレークポイントは不要

ここに画像の説明を入力

次に、簡単に行うことができます:

po [0x7f91747c71f0 recursiveDescription]

私にとっては次のようなものを返しました:

<FacebookApp.WhatsNewView: 0x7f91747c71f0; frame = (30 50; 354 636); clipsToBounds = YES; layer = <CALayer: 0x6100002370e0>>
   | <UIStackView: 0x7f91747c75f0; frame = (45 60; 264 93); layer = <CATransformLayer: 0x610000230ec0>>
   |    | <UIImageView: 0x7f916ef38c30; frame = (10.6667 0; 243 58); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x61000003b840>>
   |    | <UIStackView: 0x7f91747c8230; frame = (44.6667 58; 174.667 35); layer = <CATransformLayer: 0x6100006278c0>>
   |    |    | <FacebookApp.CopyableUILabel: 0x7f91747a80b0; baseClass = UILabel; frame = (44 0; 86.6667 16); text = 'What's New'; gestureRecognizers = <NSArray: 0x610000c4a770>; layer = <_UILabelLayer: 0x610000085550>>
   |    |    | <FacebookApp.CopyableUILabel: 0x7f916ef396a0; baseClass = UILabel; frame = (0 21; 174.667 14); text = 'Version 14.0.5c Oct 05, 2...'; gestureRecognizers = <NSArray: 0x610000c498a0>; layer = <_UILabelLayer: 0x610000087300>>
   | <UITextView: 0x7f917015ce00; frame = (45 183; 264 403); text = '   •   new Adding new feature...'; clipsToBounds = YES; gestureRecognizers = <NSArray: 0x6100000538f0>; layer = <CALayer: 0x61000042f000>; contentOffset: {0, 0}; contentSize: {264, 890}>
   |    | <<_UITextContainerView: 0x7f9170a13350; frame = (0 0; 264 890); layer = <_UITextTiledLayer: 0x6080002c0930>> minSize = {0, 0}, maxSize = {1.7976931348623157e+308, 1.7976931348623157e+308}, textContainer = <NSTextContainer: 0x610000117b20 size = (264.000000,340282346638528859811704183484516925440.000000); widthTracksTextView = YES; heightTracksTextView = NO>; exclusionPaths = 0x61000001bc30; lineBreakMode = 0>
   |    |    | <_UITileLayer: 0x60800023f8a0> (layer)
   |    |    | <_UITileLayer: 0x60800023f3c0> (layer)
   |    |    | <_UITileLayer: 0x60800023f360> (layer)
   |    |    | <_UITileLayer: 0x60800023eca0> (layer)
   |    | <UIImageView: 0x7f9170a7d370; frame = (-39 397.667; 36 2.33333); alpha = 0; opaque = NO; autoresize = TM; userInteractionEnabled = NO; layer = <CALayer: 0x60800023f4c0>>
   |    | <UIImageView: 0x7f9170a7d560; frame = (258.667 -39; 2.33333 36); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x60800023f5e0>>
   | <UIView: 0x7f916ef149c0; frame = (0 587; 354 0); layer = <CALayer: 0x6100006392a0>>
   | <UIButton: 0x7f91747a8730; frame = (0 0; 0 0); clipsToBounds = YES; opaque = NO; layer = <CALayer: 0x610000639320>>
   |    | <UIButtonLabel: 0x7f916ef00a80; frame = (0 -5.66667; 0 16); text = 'See More Details'; opaque = NO; userInteractionEnabled = NO; layer = <_UILabelLayer: 0x610000084d80>>

ご想像のとおり、私のスーパービューには 4 つのサブビューがあります。

  • stackView (stackView 自体には画像と別の stackView があります (この stackView には 2 つのカスタムラベルがあります))
  • テキストビュー
  • ビュー
  • ボタン

これは私にとってかなり新しいことですが、ビューのフレーム (およびテキストとタイプ) をデバッグするのに役立ちました。サブビューの 1 つが画面に表示されなかったので、recursiveDescription を使用して、サブビューの 1 つの幅が0... であることを認識したので、その制約を修正すると、サブビューが表示されました。

于 2017-10-25T15:24:10.580 に答える
0

AC# Xamarin バージョン:

void ListSubviewsOfView(UIView view)
{
    var subviews = view.Subviews;
    if (subviews.Length == 0) return;

    foreach (var subView in subviews)
    {
        Console.WriteLine("Subview of type {0}", subView.GetType());
        ListSubviewsOfView(subView);
    }
}

または、特定のタイプのすべてのサブビューを見つけたい場合は、次を使用します。

List<T> FindViews<T>(UIView view)
{
    List<T> allSubviews = new List<T>();
    var subviews = view.Subviews.Where(x =>  x.GetType() == typeof(T)).ToList();

    if (subviews.Count == 0) return allSubviews;

       foreach (var subView in subviews)
       {
            allSubviews.AddRange(FindViews<T>(subView));
        }

    return allSubviews;

}
于 2016-10-10T12:37:55.957 に答える
0

または、UIView 拡張機能からすべてのサブビュー (およびネストされたサブビュー) の配列を返したい場合:

func getAllSubviewsRecursively() -> [AnyObject] {
    var allSubviews: [AnyObject] = []

    for subview in self.subviews {
        if let subview = subview as? UIView {
            allSubviews.append(subview)
            allSubviews = allSubviews + subview.getAllSubviewsRecursively()
        }
    }

    return allSubviews
}
于 2015-06-04T12:28:44.433 に答える
-1

self.view.subviews は、ビューの階層を維持します。uitableviewcell のサブビューを取得するには、以下のようにする必要があります。

 for (UIView *subView in self.view.subviews) {
      if ([subView isKindOfClass:[UITableView class]]) {
            for (UIView *tableSubview in subView.subviews) {
                .......
            }
      }
 }
于 2011-08-30T13:31:50.520 に答える