Created
October 6, 2012 01:20
-
-
Save zuccoi/3843360 to your computer and use it in GitHub Desktop.
Category methods to traverse object graph and view tree.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <Foundation/Foundation.h> | |
// RLTraverseObjectGraphBlock | |
typedef void (^RLTraverseObjectGraphBlock)(id obj, NSUInteger depth, NSUInteger idx, id parent, BOOL *stop); // If you want to stop traversing completely, set YES to *stop. | |
// RLChildrenGetter | |
typedef id (^RLChildrenGetter)(id obj, NSUInteger depth, NSUInteger idx, id parent); // Return object which responds to enumerateObjetsUsingBlock: method. If you don't want to dive deeper, return nil. | |
@interface NSObject (RLTraverse) | |
- (void)traverseObjectGraphUsingBlock:(RLTraverseObjectGraphBlock)block childrenGetter:(RLChildrenGetter)childrenGetter; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "NSObject+RLTraverse.h" | |
@implementation NSObject (RLTraverse) | |
- (BOOL)_traverseObjectGraphUsingBlock:(RLTraverseObjectGraphBlock)block childrenGetter:(RLChildrenGetter)childrenGetter depth:(NSUInteger)depth index:(NSUInteger)index parent:(id)parent | |
{ | |
__block BOOL stopped = NO; | |
// Execute block | |
block(self, depth, index, parent, &stopped); | |
if (stopped) { | |
return YES; | |
} | |
// Enumerate children | |
if (childrenGetter) { | |
id children; | |
children = childrenGetter(self, depth, index, parent); | |
if ([children respondsToSelector:@selector(enumerateObjectsUsingBlock:)]) { | |
[children enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { | |
stopped = [obj _traverseObjectGraphUsingBlock:block childrenGetter:childrenGetter depth:(depth + 1) index:idx parent:self]; | |
if (stopped) { | |
*stop = stopped; | |
} | |
}]; | |
} | |
} | |
return stopped; | |
} | |
- (void)traverseObjectGraphUsingBlock:(RLTraverseObjectGraphBlock)block childrenGetter:(RLChildrenGetter)childrenGetter | |
{ | |
// Call primitive method | |
[self _traverseObjectGraphUsingBlock:block childrenGetter:childrenGetter depth:0 index:0 parent:nil]; | |
} | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import <UIKit/UIKit.h> | |
// RLTraverseViewTreeBlock | |
typedef void (^RLTraverseViewTreeBlock)(UIView *view, NSUInteger depth, NSUInteger idx, BOOL *stop); | |
@interface UIView (RLTraverse) | |
- (void)traverseViewTreeUsingBlock:(RLTraverseViewTreeBlock)block; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "NSObject+RLTraverse.h" | |
#import "UIView+RLTraverse.h" | |
@implementation UIView (RLTraverse) | |
- (void)traverseViewTreeUsingBlock:(RLTraverseViewTreeBlock)block | |
{ | |
// Traverse view tree | |
[self | |
traverseObjectGraphUsingBlock:^(id obj, NSUInteger depth, NSUInteger idx, id parent, BOOL *stop) { | |
block(obj, depth, idx, stop); | |
} | |
childrenGetter:^(UIView *view, NSUInteger depth, NSUInteger idx, id parent) { | |
return view.subviews; | |
} | |
]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment