UIView의 모든 하위보기, 하위보기 및 하위보기를 어떻게 반복 할 수 있습니까?
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;
}
}
subviews
뷰 자체를 포함하지 않고 모든 것을 제공하는 Swift 3의 솔루션 :
extension UIView {
var allSubViews : [UIView] {
var array = [self.subviews].flatMap {$0}
array.forEach { array.append(contentsOf: $0.allSubViews) }
return array
}
}
디버거를 통해이 작업을 수행하는 흥미로운 방법을 찾았습니다.
http://idevrecipes.com/2011/02/10/exploring-iphone-view-hierarchies/
이 Apple Technote를 참조하십시오.
https://developer.apple.com/library/content/technotes/tn2239/_index.html#SECUIKIT
디버거가 일시 중지되었는지 확인하고 (중단 지점을 수동으로 설정) recursiveDescription
.
생성 될 때 모든 것을 태그합니다. 그러면 하위보기를 쉽게 찾을 수 있습니다.
view = [aView viewWithTag:tag];
다음은 또 다른 Swift 구현입니다.
extension UIView {
var allSubviews: [UIView] {
return self.subviews.flatMap { [$0] + $0.allSubviews }
}
}
Ole Begemann의 도움으로. 블록 개념을 통합하기 위해 몇 줄을 추가했습니다.
UIView + HierarchyLogging.h
typedef void (^ViewActionBlock_t)(UIView *);
@interface UIView (UIView_HierarchyLogging)
- (void)logViewHierarchy: (ViewActionBlock_t)viewAction;
@end
UIView + HierarchyLogging.m
@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에서 HierarchyLogging 카테고리 사용. 이제해야 할 일을 자유롭게 할 수 있습니다.
void (^ViewActionBlock)(UIView *) = ^(UIView *view) {
if ([view isKindOfClass:[UIButton class]]) {
NSLog(@"%@", view);
}
};
[self.view logViewHierarchy: ViewActionBlock];
다음은 실제 뷰 루핑 및 중단 기능이있는 예입니다.
빠른:
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;
}
}];
새로운 기능을 만들 필요가 없습니다. Xcode로 디버깅 할 때만하십시오.
뷰 컨트롤러에서 중단 점을 설정하고이 중단 점에서 앱을 일시 중지합니다.
빈 영역을 마우스 오른쪽 버튼으로 클릭하고 Xcode의 Watch 창에서 "식 추가 ..."를 누릅니다.
다음 줄을 입력하십시오.
(NSString*)[self->_view recursiveDescription]
값이 너무 길면 마우스 오른쪽 단추로 클릭하고 "...에 대한 설명 인쇄"를 선택하십시오. 콘솔 창에서 self.view의 모든 하위보기를 볼 수 있습니다. self.view의 하위보기를 보지 않으려면 self-> _ view를 다른 것으로 변경하십시오.
끝난! gdb가 없습니다!
다음은 재귀 코드입니다.
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];
}
}
그건 그렇고, 나는 이런 종류의 작업을 돕기 위해 오픈 소스 프로젝트를 만들었습니다. 정말 쉽고 Objective-C 2.0 블록을 사용하여 계층 구조의 모든 뷰에서 코드를 실행합니다.
https://github.com/egold/UIViewRecursion
예:
-(void)makeAllSubviewsGreen
{
[self.view runBlockOnAllSubviews:^(UIView *view) {
view.backgroundColor = [UIColor greenColor];
}];
}
다음은 위 의 Ole Begemann의 답변 에 대한 변형으로 , 계층 구조를 설명하기 위해 들여 쓰기를 추가합니다.
// 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
The code posted in this answer traverses all windows and all views and all of their subviews. It was used to dump a printout of the view hierarchy to NSLog but you can use it as a basis for any traversal of the view hierarchy. It uses a recursive C function to traverse the view tree.
I wrote a category some time back to debug some views.
IIRC, the posted code is the one that worked. If not, it will point you in the right direction. Use at own risk, etc.
This displays the hierarchy level as well
@implementation UIView (ViewHierarchyLogging)
- (void)logViewHierarchy:(int)level
{
NSLog(@"%d - %@", level, self);
for (UIView *subview in self.subviews)
{
[subview logViewHierarchy:(level+1)];
}
}
@end
Wish I'd found this page first, but if (for some reason) you want to do this non-recursively, not in a Category, and with more lines of code
I think all of the answers using recursion (except for the debugger option) used categories. If you don't need/want a category, you can just use a instance method. For instance, if you need to get an array of all labels in your view hierarchy, you could do this.
@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
}
}
The method below creates one or more mutable arrays, then loops through the subviews of the input view. In doing so it adds the initial subview then queries as to whether there are any subviews of that subview. If true, it calls itself again. It does so until the all the views of the hierarchy have been added.
-(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;
}
Call using:
NSArray * subviews = [self allSubs:someView];
'Program Tip' 카테고리의 다른 글
Xcode 7 오류 ITMS-90474 : "잘못된 번들", Apple에 제출할 수 없음 (0) | 2020.10.15 |
---|---|
빈혈 도메인 모델 : 장점 / 단점 (0) | 2020.10.15 |
Eclipse IDE보기가 사라짐-다시 가져 오는 방법 (0) | 2020.10.15 |
C # Winforms의 레이블에 힌트 또는 도구 설명을 추가하려면 어떻게해야합니까? (0) | 2020.10.15 |
터미널을 사용하여 실 버전을 업그레이드하는 방법은 무엇입니까? (0) | 2020.10.15 |