मैं एक में सभी साक्षात्कारों को सूचीबद्ध करना चाहता हूं UIViewController
। मैंने कोशिश की self.view.subviews
, लेकिन सभी उप-सूचियों को सूचीबद्ध नहीं किया गया है, उदाहरण के लिए, साक्षात्कार में UITableViewCell
नहीं मिले हैं। कोई उपाय?
मैं एक में सभी साक्षात्कारों को सूचीबद्ध करना चाहता हूं UIViewController
। मैंने कोशिश की self.view.subviews
, लेकिन सभी उप-सूचियों को सूचीबद्ध नहीं किया गया है, उदाहरण के लिए, साक्षात्कार में UITableViewCell
नहीं मिले हैं। कोई उपाय?
जवाबों:
आपको उप-विचारों को पुनरावृत्ति करना होगा।
- (void)listSubviewsOfView:(UIView *)view {
// Get the subviews of the view
NSArray *subviews = [view subviews];
// Return if there are no subviews
if ([subviews count] == 0) return; // COUNT CHECK LINE
for (UIView *subview in subviews) {
// Do what you want to do with the subview
NSLog(@"%@", subview);
// List the subviews of subview
[self listSubviewsOfView:subview];
}
}
जैसा कि @Greg Meletic द्वारा टिप्पणी की गई है, आप ऊपर दिए गए COUNT CHECK LINE को छोड़ सकते हैं।
recursiveDescription
@natbro से अधिक सरल उत्तर की जांच करें - stackoverflow.com/a/8962824/429521
दृश्य पदानुक्रम को डंप करने के लिए निर्मित xcode / gdb का तरीका उपयोगी है - प्रतिदेयता, प्रतिलेखन, http://developer.apple.com/library/ios/#technotes/tn2239/_index.html
यह अधिक संपूर्ण दृश्य पदानुक्रम को आउटपुट करता है जो आपको उपयोगी लग सकता है:
> 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>>
[_myToolbar recursiveDescription]
मेरे कोड में या कहीं और कवि को कहां रखा जाए ।
आपको पुनरावर्ती प्रिंट करने की आवश्यकता है, यह विधि भी दृश्य की गहराई के आधार पर टैब करती है
-(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];
}
}
यहाँ स्विफ्ट संस्करण है
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)
}
}
मैं पार्टी के लिए थोड़ा लेट हूँ, लेकिन थोड़ा और सामान्य समाधान:
@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
यदि आप चाहते हैं कि यह एक सरणी है UIView
, तो यह एक लाइनर समाधान है ( स्विफ्ट 4+ ):
extension UIView {
var allSubviews: [UIView] {
return self.subviews.reduce([UIView]()) { $0 + [$1] + $1.allSubviews }
}
}
extension UIView {
private func subviews(parentView: UIView, level: Int = 0, printSubviews: Bool = false) -> [UIView] {
var result = [UIView]()
if level == 0 && printSubviews {
result.append(parentView)
print("\(parentView.viewInfo)")
}
for subview in parentView.subviews {
if printSubviews { print("\(String(repeating: "-", count: level))\(subview.viewInfo)") }
result.append(subview)
if subview.subviews.isEmpty { continue }
result += subviews(parentView: subview, level: level+1, printSubviews: printSubviews)
}
return result
}
private var viewInfo: String { return "\(classForCoder), frame: \(frame))" }
var allSubviews: [UIView] { return subviews(parentView: self) }
func printSubviews() { _ = subviews(parentView: self, printSubviews: true) }
}
view.printSubviews()
print("\(view.allSubviews.count)")
मेरे तरीके से, यूआईवीवाई की श्रेणी या विस्तार दूसरों की तुलना में बहुत बेहतर है और पुनरावर्ती सभी साक्षात्कार प्राप्त करने के लिए महत्वपूर्ण बिंदु है
और अधिक जानें:
https://github.com/ZhipingYang/XYDebugView
@implementation UIView (Recurrence)
- (NSArray<UIView *> *)recurrenceAllSubviews
{
NSMutableArray <UIView *> *all = @[].mutableCopy;
void (^getSubViewsBlock)(UIView *current) = ^(UIView *current){
[all addObject:current];
for (UIView *sub in current.subviews) {
[all addObjectsFromArray:[sub recurrenceAllSubviews]];
}
};
getSubViewsBlock(self);
return [NSArray arrayWithArray:all];
}
@end
उदाहरण
NSArray *views = [viewController.view recurrenceAllSubviews];
extension UIView {
func recurrenceAllSubviews() -> [UIView] {
var all = [UIView]()
func getSubview(view: UIView) {
all.append(view)
guard view.subviews.count>0 else { return }
view.subviews.forEach{ getSubview(view: $0) }
}
getSubview(view: self)
return all
}
}
उदाहरण
let views = viewController.view.recurrenceAllSubviews()
सीधे, सभी उप-साक्षात्कार प्राप्त करने के लिए अनुक्रम फ़ंक्शन का उपयोग करें
let viewSequence = sequence(state: [viewController.view]) { (state: inout [UIView] ) -> [UIView]? in
guard state.count > 0 else { return nil }
defer {
state = state.map{ $0.subviews }.flatMap{ $0 }
}
return state
}
let views = viewSequence.flatMap{ $0 }
UITableViewCell में सब-प्रिंट नहीं होने का कारण यह है कि आपको शीर्ष स्तर के सभी साक्षात्कारों को आउटपुट करना होगा। सेल के साक्षात्कार आपके विचार के सीधे उप-साक्षात्कार नहीं हैं।
UITableViewCell के उप-साक्षात्कार प्राप्त करने के लिए, आपको यह निर्धारित करने की आवश्यकता है कि कौन से सब-वे UITableViewell के हैं (उपयोग करके isKindOfClass:
आपके प्रिंट लूप में ) और फिर यह सबव्यू के माध्यम से लूप हैं।
संपादित करें: आसान UIView डिबगिंग पर यह ब्लॉग पोस्ट संभावित रूप से मदद कर सकता है
मैंने एक व्यू कंट्रोलर द्वारा रखे गए सभी विचारों को सूचीबद्ध करने के लिए एक श्रेणी लिखी है जो पहले पोस्ट किए गए उत्तरों से प्रेरित है।
@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)]);
एक ही काम करने के लिए उपयोग कर सकते हैं , और मुझे लगता है कि यह मेरे कार्यान्वयन से अधिक कुशल है।
सरल स्विफ्ट उदाहरण:
var arrOfSub = self.view.subviews
print("Number of Subviews: \(arrOfSub.count)")
for item in arrOfSub {
print(item)
}
आप एक फैंसी ऐरे ट्रिक को आजमा सकते हैं, जैसे:
[self.view.subviews makeObjectsPerformSelector: @selector(printAllChildrenOfView)];
कोड की सिर्फ एक पंक्ति। बेशक, आपको अपने printAllChildrenOfView
पैरामीटर को समायोजित करने की आवश्यकता हो सकती है ताकि कोई पैरामीटर न लिया जा सके या एक नई विधि न बनाई जा सके।
स्विफ्ट 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()
यह इस उत्तर का पुनर्लेखन है :
आपको सबसे पहले उस ऑब्जेक्ट का पॉइंटर / रेफरेंस प्राप्त करना होगा जिसे आप उसके सभी सबव्यू को प्रिंट करना चाहते हैं। कभी-कभी आपको उस वस्तु को उसके सबव्यू के माध्यम से एक्सेस करना आसान लगता है। की तरह po someSubview.superview
। यह आपको कुछ इस तरह देगा:
Optional<UIView>
▿ some : <FacebookApp.WhatsNewView: 0x7f91747c71f0; frame = (30 50; 354 636); clipsToBounds = YES; layer = <CALayer: 0x6100002370e0>>
superview
0x7f91747c71f0
पर्यवेक्षक के लिए सूचक है।सुपर व्यू प्रिंट करने के लिए, आपको ब्रेकपॉइंट्स का उपयोग करना चाहिए।
अब इस चरण को करने के लिए आप 'व्यू डिबग पदानुक्रम' पर क्लिक कर सकते हैं। ब्रेकपाइंट की कोई आवश्यकता नहीं है
तब आप आसानी से कर सकते थे:
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 साक्षात्कार हैं:
यह मेरे लिए काफी नया है, लेकिन इससे मुझे अपने विचारों के फ्रेम (और पाठ और प्रकार) को डीबग करने में मदद मिली है। मेरा एक साक्षात्कार स्क्रीन पर दिखाई नहीं दे रहा था, इसलिए पुनरावर्ती लेखन का उपयोग किया और मुझे अपने सबवू में से एक की चौड़ाई का एहसास हुआ 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
}
एसी # ज़मारिन संस्करण:
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;
}
मैंने इसे UIView
केवल अच्छे पेड़ के प्रारूप के साथ मुद्रित करने के लिए अनुक्रमणिका को पारित करने वाले फ़ंक्शन को कॉल करने की श्रेणी में किया है । यह जेम्स वेबस्टर द्वारा पोस्ट किए गए उत्तर का एक और विकल्प है ।
#pragma mark - Views Tree
- (void)printSubviewsTreeWithIndex:(NSInteger)index
{
if (!self)
{
return;
}
NSString *tabSpace = @"";
@autoreleasepool
{
for (NSInteger x = 0; x < index; x++)
{
tabSpace = [tabSpace stringByAppendingString:@"\t"];
}
}
NSLog(@"%@%@", tabSpace, self);
if (!self.subviews)
{
return;
}
@autoreleasepool
{
for (UIView *subView in self.subviews)
{
[subView printViewsTreeWithIndex:index++];
}
}
}
मुझे उम्मीद है यह मदद करेगा :)
- (NSString *)recusiveDescription:(UIView *)view
{
NSString *s = @"";
NSArray *subviews = [view subviews];
if ([subviews count] == 0) return @"no subviews";
for (UIView *subView in subviews) {
s = [NSString stringWithFormat:@"<%@; frame = (%f %f : %f %f) \n ",NSStringFromClass([subView class]), subView.frame.origin.x, subView.frame.origin.y ,subView.frame.size.width, subView.frame.size.height];
[self recusiveDescription:subView];
}
return s;
}
self.view.subviews विचारों के उत्तराधिकार को बनाए रखता है। यदि आप नीचे दिए गए कुछ करने के लिए uitableviewcell के साक्षात्कार प्राप्त करते हैं।
for (UIView *subView in self.view.subviews) {
if ([subView isKindOfClass:[UITableView class]]) {
for (UIView *tableSubview in subView.subviews) {
.......
}
}
}