我在我的应用程序中添加了一个功能,用户可以在其中更改颜色方案,因此我需要更改屏幕上标签的颜色。我通过循环UIView来做到这一点,如果我找到一个标签,我会改变颜色。
这很好用,但我不想更改属于segmentedControls或出现在导航栏中的标签的颜色。
我的问题是,如何判断UILabel是否实际嵌入控件中,以便我可以跳过它?此代码对我不起作用:
if([v isKindOfClass:[UILabel class]] && ![v.superview isKindOfClass:[UISegmentedControl class]] )
{
UILabel *label = (UILabel *)v;
[label setTextColor:[UIColor blackColor]];
}
答案 0 :(得分:3)
我创建了一个UISegmentedControl并在调试器中停止,然后在其上调用recursiveDescription
方法(recursiveDescription
是一个私有方法,但它可以在iOS Debugging Magic中使用)。它揭示了UISegmentedControl中的标签实际上是UISegmentLabel
s,根据你的代码将它们变为黑色必须是UILabel
的子类。你的代码不起作用的原因是他们的直接超级视图显然是UISegment
,一个用于实现UISegmentedControl
的私有类。
<UISegmentedControl: 0x8e30130; frame = (99 114; 123 29); opaque = NO; autoresize = RM+BM; layer = <CALayer: 0x8e30250>>
| <UISegment: 0x8e304a0; frame = (62 0; 61 29); opaque = NO; layer = <CALayer: 0x8e305f0>>
| | <UISegmentLabel: 0x8e309d0; frame = (7 6; 47 16); text = 'Second'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x8e30ae0>>
| | <UIImageView: 0x8e32510; frame = (61 0; 1 1); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; tag = -1030; layer = <CALayer: 0x8e325e0>>
| <UISegment: 0x8e34bf0; frame = (0 0; 61 29); opaque = NO; layer = <CALayer: 0x8e34410>>
| | <UISegmentLabel: 0x8e34d30; frame = (17 6; 27 16); text = 'First'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x8e34e60>>
| | <UIImageView: 0x8e149e0; frame = (61 0; 1 1); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; tag = -1030; layer = <CALayer: 0x8e0ba60>>
您可以选择几条道路:
UISegment
类的超级视图,不建议这样做,因为它依赖于不稳定的私有API UISegmentLabel
,则无法更改颜色,因为它依赖于不稳定的私有API而不推荐使用您可以检查超级视图链的整个(或至少几个部分)。我有一个Cocoapod MTRecursiveKVC,它允许你编写代码来执行此操作:
// Recursively gets the superview property until it is nil
NSArray *superviewChain = [view recursiveValueForKey:@"superview"];
// Now iterate through the array, checking for a view being a UISegmentedControl
只要你只是遍历UILabel
的超级视图,你应该在性能方面做得很好,但请注意,手动输入你自己的解决方案会更快(我的方法更通用,因为它使用KVC,但是这会增加开销与纯方法调用的关系,并且一旦找到UISegmentedControl
超级视图,你的内容也可能会突破循环。
(推荐方法)您可以撤消循环方法。如果您从应用程序的UIWindow
(或足够高的视图)开始,您可以超越层次结构,并且只有在没有UISegmentedControl时才进一步追求分支。如果它作为UIView
上的类别实现,那么这就是它的样子(我实际上没有对此进行测试......)
- (void)changeColorOfSubviews
{
if ([self isKindOfClass:[UILabel class]]) { /* change color */ }
for (UIView *subview in self.subviews) {
if (![subview isKindOfClass:[UISegmentedControl class]]) {
[subview changeColorOfSubviews];
}
}
}
#4是我推荐的方法,因为我发现递归非常适合UIViews
的树结构,因为我已经为你提供了代码:)
这是一个说明方法编号4的图表,其中遵循黑色路径,红色路径是我们停止跟随分支的地方,灰色路径永远不会被评估(因为我们到达之前达到了红色):
答案 1 :(得分:1)
为了完整性,这是我的最终代码。再次感谢MaxGabriel的回答。
新文件,Objective-C类别(UIView)
// UIView+UIMods.m
// ATB iPad
//
// Created by A Smith on 10/4/13.
//
//
#import "UIView+UIMods.h"
#import "Colors.h"
- (void)changeColorOfLabels:(int)hiContrast
{
if ([self isKindOfClass:[UILabel class]]) { // if we are currently in a UILabel view
/* change color */
UILabel *label = (UILabel *)self;
NSString *ver = [UIDevice currentDevice].systemVersion;
int majorVer = [ver integerValue];
if( hiContrast ){
if( ![label.superview isKindOfClass:[UIButton class]] ){
[label setTextColor:[UIColor blackColor]];
[label setBackgroundColor:[UIColor whiteColor]];
} else {
if( majorVer >= 7 ){
[label setTextColor:[Colors iOS7ButtonColor]];
}
}
} else {
if( ![label.superview isKindOfClass:[UIButton class]] ){
[label setTextColor:[UIColor whiteColor]];
[label setBackgroundColor:[Colors darkBkgColor]];
} else {
if( majorVer >= 7 ){
[label setTextColor:[Colors iOS7ButtonColor]];
}
}
}
}
for (UIView *subview in self.subviews) {
if (![subview isKindOfClass:[UISegmentedControl class]] && ![subview.superview isKindOfClass:[UITextField class]] ) {
[subview changeColorOfLabels:hiContrast]; // only recurse down if it's the type of view we want to modify the label for
}
}
}
和.h文件:
@interface UIView (UIMods){
}
- (void)changeColorOfLabels:(int)hiContrast;
@end
就像这样,
UIView *aView = theView.view;
[aView changeColorOfLabels:globalHighContrast];
我看到一个很好的建议是将.h文件导入添加到.pch文件中,以便在任何地方都可以使用此添加内容,您不必在本地导入任何内容。
#ifdef __OBJC__
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "UIView+UIMods.h"
#endif