外观代理和图层

Posted

技术标签:

【中文标题】外观代理和图层【英文标题】:Appearance Proxies & Layers 【发布时间】:2012-01-08 15:24:36 【问题描述】:

是否可以使用 ios 5 外观代理来重构在图层上设置属性的代码?

_button.layer.cornerRadius = 5.0f;
_button.layer.borderWidth = 1.0f;
_button.layer.borderColor = [[UIColor blackColor] CGColor];
_button.layer.masksToBounds = YES;

【问题讨论】:

我觉得目前错误的答案被标记为正确:-) Tieme's answer 专门针对香草 UIButton 是正确的。但是,如果您乐于以Sandy's answer 中所示的简单方式扩展 UIButton,则可以实现您在问题中要求的效果。 【参考方案1】:

接受的答案不正确。您可以在图层上设置属性,但是,您需要将视图子类化并通过访问器公开图层属性。

为了说明,我将只使用问题中的一个属性,cornerRadius

第 1 步: 实现一个 UIButton 子类。

#import <UIKit/UIKit.h>

@interface MyRoundedCornerButton : UIButton

@end

第 2 步: 添加标记为UI_APPEARANCE_SELECTOR 的属性。

#import <UIKit/UIKit.h>

@interface MyRoundedCornerButton : UIButton

@property (readwrite, nonatomic) CGFloat cornerRadius UI_APPEARANCE_SELECTOR;

@end

第 3 步: 实现新类。

@implementation MyRoundedCornerButton

- (void)setCornerRadius:(CGFloat)cornerRadius

    self.layer.cornerRadius = cornerRadius;


@end

第 4 步: 在外观代理中设置圆角半径。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

    ...
    [MyRoundedCornerButton appearance].cornerRadius = 10.0;
    ...

第 5 步: 然后在 IB 中(或您定义创建视图的任何地方),将自定义视图类设置为(或实例化)MyRoundedCornerButton 而不是 UIButton。

注意事项: 我这样做是为了在我的应用程序中应用一个易于更改的渐变背景。就我而言,所有视图控制器的根视图都使用自定义类。这个自定义类通过+(Class)layerClass 方法提供了一个CAGradientLayer。然后,我使用UI_APPEARANCE_SELECTOR 标签公开底层渐变层的colorslocations 属性。在应用程序初始化时设置一次可以自定义整个应用程序。您甚至可以向用户公开颜色,以允许他们完全自定义各种控件的颜色。

【讨论】:

谢谢!不应该是MyRoundedCornerButton : UIButton吗? 另一个不相关的建议 - 如果您使用 NSNumber 作为圆角半径的类型,您还可以使用 User Defined Runtime Attributes 覆盖 IB 的外观默认值。 @Benjohn,你是对的,它应该是 UIButton(我会更新我的答案)。使用User Defined Runtime Attributes 设置这些值有一些注意事项(例如,当您有多个相互影响的 UI_APPEARANCE_SELECTOR 成员时),但在大多数情况下,您不会遇到这些问题。此外,适用于此的新内容是,如果您使用 Swift,则不再需要 UI_APPEARANCE_SELECTOR 注释,您可以使用 @IBInspectable 向您的成员公开值,以便在 IB 中更轻松地编辑它们。 我想知道是否可以将这些 UI_APPEARANCE_SELECTOR 方法添加到一个类别中,以便为所有 UIView 实例提供它们。我猜“不!”,但是,嘿,如果可以的话,它会是净值,对吧?! @Benjohn,实际上您可以将它们添加到类别中。我已经为 UIView 添加了可在我的应用程序中的任何 UIView 上设置的borderWidth 和borderColor 属性。【参考方案2】:

不.. Apple 说:

要支持外观定制,类必须符合 UIAppearanceContainer 协议和相关的访问器方法必须是 标有 UI_APPEARANCE_SELECTOR。

http://developer.apple.com/library/ios/#documentation/uikit/reference/UIAppearance_Protocol/Reference/Reference.html

而 UIButton 没有。

编辑: 并且 UIButton 没有任何标有 UI_APPEARANCE_SELECTOR 的方法。

【讨论】:

UIButton 实际上支持外观代理,事实上你可以看到在 2011 年 WWDC 提供的“自定义 UIKit 控件的外观”会话中 Apple 提供的演示中使用了 UIButton。链接developer.apple.com/videos/wwdc/2011 (看大约 28 分钟) OP 不是询问控件视图的 CALayer,而不是专门询问 UIButton 吗?

以上是关于外观代理和图层的主要内容,如果未能解决你的问题,请参考以下文章

Geoserver 代理基本 URL 不用于图层预览

代理、包装器或外观类之间有啥区别

代理 适配 外观

重置文本时覆盖外观代理

Swift 中的外观代理 (iOS)

深入浅出,对于代理模式的理解(代理模式与外观模式的区别)