मैं एक यूआईवीवाई के सभी साक्षात्कारों और उनके साक्षात्कारों और उनके साक्षात्कारों के माध्यम से कैसे लूप कर सकता हूं?
मैं एक यूआईवीवाई के सभी साक्षात्कारों और उनके साक्षात्कारों और उनके साक्षात्कारों के माध्यम से कैसे लूप कर सकता हूं?
जवाबों:
पुनरावर्तन का उपयोग करें:
// UIView+HierarchyLogging.h
@interface UIView (ViewHierarchyLogging)
- (void)logViewHierarchy;
@end
// UIView+HierarchyLogging.m
@implementation UIView (ViewHierarchyLogging)
- (void)logViewHierarchy
{
NSLog(@"%@", self);
for (UIView *subview in self.subviews)
{
[subview logViewHierarchy];
}
}
@end
// In your implementation
[myView logViewHierarchy];
अच्छी तरह से यहाँ UIView वर्ग के लिए पुनरावृत्ति और एक आवरण (श्रेणी / विस्तार) का उपयोग कर मेरा समाधान है।
// UIView+viewRecursion.h
@interface UIView (viewRecursion)
- (NSMutableArray*) allSubViews;
@end
// UIView+viewRecursion.m
@implementation UIView (viewRecursion)
- (NSMutableArray*)allSubViews
{
NSMutableArray *arr=[[[NSMutableArray alloc] init] autorelease];
[arr addObject:self];
for (UIView *subview in self.subviews)
{
[arr addObjectsFromArray:(NSArray*)[subview allSubViews]];
}
return arr;
}
@end
उपयोग: अब आपको सभी उप दृश्यों के माध्यम से लूपिंग करना चाहिए और आवश्यकतानुसार उन्हें हेरफेर करना चाहिए।
//disable all text fields
for(UIView *v in [self.view allSubViews])
{
if([v isKindOfClass:[UITextField class]])
{
((UITextField*)v).enabled=NO;
}
}
allSubViews
फ़ंक्शन में मेमोरी लीक हैं : आपको या तो सरणी बनाना चाहिए [[[NSMutableArray alloc] init] autorelease]
या जैसा कि [NSMutableArray array]
(जो समान है)।
यहाँ एक और स्विफ्ट कार्यान्वयन है:
extension UIView {
var allSubviews: [UIView] {
return self.subviews.flatMap { [$0] + $0.allSubviews }
}
}
स्विफ्ट 3 में एक समाधान जो subviews
बिना किसी दृश्य के सभी को शामिल करता है:
extension UIView {
var allSubViews : [UIView] {
var array = [self.subviews].flatMap {$0}
array.forEach { array.append(contentsOf: $0.allSubViews) }
return array
}
}
nil
एक सरणी से तत्वों को निकालता है , सुरक्षा के लिए जब साक्षात्कार में बुलाते हैं allSubViews
।
जब यह बनाया जाता है तो मैं सब कुछ टैग करता हूं। फिर कोई भी सबव्यू खोजना आसान है।
view = [aView viewWithTag:tag];
बस डिबगर के माध्यम से ऐसा करने का एक दिलचस्प तरीका मिला:
http://idevrecipes.com/2011/02/10/exploring-iphone-view-hierarchies/
इस Apple तकनीक का संदर्भ:
https://developer.apple.com/library/content/technotes/tn2239/_index.html#SIOUUIT
बस सुनिश्चित करें कि आपका डिबगर रुका हुआ है (या तो इसे मैन्युअल रूप से विराम दें) और आप इसके लिए पूछ सकते हैं recursiveDescription
।
यहां वास्तविक दृश्य लूपिंग और ब्रेकिंग कार्यक्षमता के साथ एक उदाहरण है।
स्विफ्ट:
extension UIView {
func loopViewHierarchy(block: (_ view: UIView, _ stop: inout Bool) -> ()) {
var stop = false
block(self, &stop)
if !stop {
self.subviews.forEach { $0.loopViewHierarchy(block: block) }
}
}
}
कॉल उदाहरण:
mainView.loopViewHierarchy { (view, stop) in
if view is UIButton {
/// use the view
stop = true
}
}
उलटा लूपिंग:
extension UIView {
func loopViewHierarchyReversed(block: (_ view: UIView, _ stop: inout Bool) -> ()) {
for i in stride(from: self.highestViewLevel(view: self), through: 1, by: -1) {
let stop = self.loopView(view: self, level: i, block: block)
if stop {
break
}
}
}
private func loopView(view: UIView, level: Int, block: (_ view: UIView, _ stop: inout Bool) -> ()) -> Bool {
if level == 1 {
var stop = false
block(view, &stop)
return stop
} else if level > 1 {
for subview in view.subviews.reversed() {
let stop = self.loopView(view: subview, level: level - 1, block: block)
if stop {
return stop
}
}
}
return false
}
private func highestViewLevel(view: UIView) -> Int {
var highestLevelForView = 0
for subview in view.subviews.reversed() {
let highestLevelForSubview = self.highestViewLevel(view: subview)
highestLevelForView = max(highestLevelForView, highestLevelForSubview)
}
return highestLevelForView + 1
}
}
कॉल उदाहरण:
mainView.loopViewHierarchyReversed { (view, stop) in
if view is UIButton {
/// use the view
stop = true
}
}
उद्देश्य सी:
typedef void(^ViewBlock)(UIView* view, BOOL* stop);
@interface UIView (ViewExtensions)
-(void) loopViewHierarchy:(ViewBlock) block;
@end
@implementation UIView (ViewExtensions)
-(void) loopViewHierarchy:(ViewBlock) block {
BOOL stop = NO;
if (block) {
block(self, &stop);
}
if (!stop) {
for (UIView* subview in self.subviews) {
[subview loopViewHierarchy:block];
}
}
}
@end
कॉल उदाहरण:
[mainView loopViewHierarchy:^(UIView* view, BOOL* stop) {
if ([view isKindOfClass:[UIButton class]]) {
/// use the view
*stop = YES;
}
}];
ओले बेगेमैन की मदद से। मैंने इसमें ब्लॉक कॉन्सेप्ट को शामिल करने के लिए कुछ लाइनें जोड़ीं।
उविवि + पदानुक्रम
typedef void (^ViewActionBlock_t)(UIView *);
@interface UIView (UIView_HierarchyLogging)
- (void)logViewHierarchy: (ViewActionBlock_t)viewAction;
@end
उविवि + पदानुक्रम
@implementation UIView (UIView_HierarchyLogging)
- (void)logViewHierarchy: (ViewActionBlock_t)viewAction {
//view action block - freedom to the caller
viewAction(self);
for (UIView *subview in self.subviews) {
[subview logViewHierarchy:viewAction];
}
}
@end
अपने ViewController में पदानुक्रम श्रेणी का उपयोग करना। अब आपके पास वह स्वतंत्रता है जो आपको करने की आवश्यकता है।
void (^ViewActionBlock)(UIView *) = ^(UIView *view) {
if ([view isKindOfClass:[UIButton class]]) {
NSLog(@"%@", view);
}
};
[self.view logViewHierarchy: ViewActionBlock];
कोई नया फ़ंक्शन बनाने की आवश्यकता नहीं है। एक्सकोड के साथ डिबगिंग करते समय बस इसे करें।
एक व्यू कंट्रोलर में एक ब्रेकपॉइंट सेट करें, और इस ब्रेकपॉइंट पर ऐप पॉज़ करें।
खाली क्षेत्र पर राइट क्लिक करें और Xcode की वॉच विंडो में "Add Expression ..." दबाएं।
इस लाइन को इनपुट करें:
(NSString*)[self->_view recursiveDescription]
यदि मान बहुत लंबा है, तो उसे क्लिक करें और "प्रिंट विवरण ऑफ ..." चुनें। आप कंसोल विंडो में self.view के सभी उप-साक्षात्कार देखेंगे। यदि आप स्वयं का साक्षात्कार नहीं देखना चाहते हैं, तो स्वयं -> _ कुछ और देखें।
किया हुआ! नहीं जीडीबी!
यहाँ एक पुनरावर्ती कोड है: -
for (UIView *subViews in yourView.subviews) {
[self removSubviews:subViews];
}
-(void)removSubviews:(UIView *)subView
{
if (subView.subviews.count>0) {
for (UIView *subViews in subView.subviews) {
[self removSubviews:subViews];
}
}
else
{
NSLog(@"%i",subView.subviews.count);
[subView removeFromSuperview];
}
}
वैसे, मैंने इस तरह के काम में मदद करने के लिए एक ओपन सोर्स प्रोजेक्ट बनाया। यह वास्तव में आसान है, और एक पदानुक्रम में सभी विचारों पर कोड निष्पादित करने के लिए उद्देश्य-सी 2.0 ब्लॉकों का उपयोग करता है।
https://github.com/egold/UIViewRecursion
उदाहरण:
-(void)makeAllSubviewsGreen
{
[self.view runBlockOnAllSubviews:^(UIView *view) {
view.backgroundColor = [UIColor greenColor];
}];
}
यहाँ ऊपर ओले बेगमैन के उत्तर पर भिन्नता है, जो पदानुक्रम को दर्शाने के लिए इंडेंटेशन जोड़ता है:
// UIView+HierarchyLogging.h
@interface UIView (ViewHierarchyLogging)
- (void)logViewHierarchy:(NSString *)whiteSpaces;
@end
// UIView+HierarchyLogging.m
@implementation UIView (ViewHierarchyLogging)
- (void)logViewHierarchy:(NSString *)whiteSpaces {
if (whiteSpaces == nil) {
whiteSpaces = [NSString string];
}
NSLog(@"%@%@", whiteSpaces, self);
NSString *adjustedWhiteSpaces = [whiteSpaces stringByAppendingFormat:@" "];
for (UIView *subview in self.subviews) {
[subview logViewHierarchy:adjustedWhiteSpaces];
}
}
@end
इस उत्तर में पोस्ट किया गया कोड सभी विंडो और सभी विचारों और उनके सभी साक्षात्कारों का पता लगाता है। यह NSLog के लिए पदानुक्रम के एक प्रिंटआउट को डंप करने के लिए उपयोग किया गया था, लेकिन आप इसे पदानुक्रम के किसी भी ट्रैवर्सल के आधार के रूप में उपयोग कर सकते हैं। यह दृश्य ट्री को पार करने के लिए एक पुनरावर्ती C फ़ंक्शन का उपयोग करता है।
मुझे लगता है कि सभी उत्तर पुनरावृत्ति (डिबगर विकल्प को छोड़कर) का उपयोग करते हुए श्रेणियों का उपयोग करते हैं। यदि आपको किसी श्रेणी की आवश्यकता नहीं है, तो आप केवल एक इंस्टेंस विधि का उपयोग कर सकते हैं। उदाहरण के लिए, यदि आपको पदानुक्रम में सभी लेबल की एक सरणी प्राप्त करने की आवश्यकता है, तो आप ऐसा कर सकते हैं।
@interface MyViewController ()
@property (nonatomic, retain) NSMutableArray* labelsArray;
@end
@implementation MyViewController
- (void)recursiveFindLabelsInView:(UIView*)inView
{
for (UIView *view in inView.subviews)
{
if([view isKindOfClass:[UILabel class]])
[self.labelsArray addObject: view];
else
[self recursiveFindLabelsInView:view];
}
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.labelsArray = [[NSMutableArray alloc] init];
[self recursiveFindLabelsInView:self.view];
for (UILabel *lbl in self.labelsArray)
{
//Do something with labels
}
}
नीचे दी गई विधि एक या अधिक परिवर्तनशील सरणियों का निर्माण करती है, फिर इनपुट दृश्य के साक्षात्कार के माध्यम से लूप करती है। ऐसा करने पर यह आरंभिक सबव्यू जोड़ता है और फिर उस सबव्यू के किसी भी साक्षात्कार के रूप में प्रश्न करता है। अगर सच है, तो यह फिर से खुद को बुलाता है। ऐसा तब तक होता है जब तक कि पदानुक्रम के सभी विचारों को जोड़ नहीं दिया गया हो।
-(NSArray *)allSubs:(UIView *)view {
NSMutableArray * ma = [NSMutableArray new];
for (UIView * sub in view.subviews){
[ma addObject:sub];
if (sub.subviews){
[ma addObjectsFromArray:[self allSubs:sub]];
}
}
return ma;
}
कॉल का उपयोग करें:
NSArray * subviews = [self allSubs:someView];