UIView의 모든 하위보기, 하위보기 및 하위보기를 어떻게 반복 할 수 있습니까?
답변
재귀 사용 :
// 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;
}
}
답변
다음은 또 다른 Swift 구현입니다.
extension UIView {
var allSubviews: [UIView] {
return self.subviews.flatMap { [$0] + $0.allSubviews }
}
}
답변
subviews
뷰 자체를 포함하지 않고 모든 것을 제공하는 Swift 3의 솔루션 :
extension UIView {
var allSubViews : [UIView] {
var array = [self.subviews].flatMap {$0}
array.forEach { array.append(contentsOf: $0.allSubViews) }
return array
}
}
답변
생성 될 때 모든 것을 태그합니다. 그러면 하위보기를 쉽게 찾을 수 있습니다.
view = [aView viewWithTag:tag];
답변
디버거를 통해이 작업을 수행하는 흥미로운 방법을 찾았습니다.
http://idevrecipes.com/2011/02/10/exploring-iphone-view-hierarchies/
이 Apple Technote를 참조하십시오.
https://developer.apple.com/library/content/technotes/tn2239/_index.html#SECUIKIT
디버거가 일시 중지되었는지 확인하고 (중단 지점을 수동으로 설정) 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
}
}
목표 -C :
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;
}
}];
