24

我正在继承 UIButton,我想要的是将按钮类型设置为 Round Rect。

按钮.h

@interface Button : UIButton {}
    - (void)initialize;
@end

按钮.m

@implementation Button

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self initialize];
    }
    return self;
}


-(id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if(self){
        [self initialize];
    }
    return self;
}

- (void)initialize
{
    self.titleLabel.font = [UIFont systemFontOfSize:20];
    self.titleLabel.textColor = [UIColor redColor];
    self.titleLabel.textAlignment = UITextAlignmentCenter;
   //[UIButton buttonWithType:UIButtonTypeRoundedRect];
}

@end

在这里我试过[UIButton buttonWithType:UIButtonTypeRoundedRect]但它不起作用。谁能建议如何使它工作?

我知道在之前的许多帖子中都说不推荐对 UIButton 进行子类化,但事实上在 Developer's Docs 中没有提到不对其进行子类化。

4

8 回答 8

13

您可以在 CocoaBuilder 的线程How to subclass UIButton?中找到讨论。有帮助,尤其是Jack Nutting 建议忽略 buttonType

请注意,这种方式 buttonType 没有显式设置为任何内容,这可能意味着它是 UIButtonTypeCustom。文档似乎并没有真正指定这一点,但由于这是枚举中的 0 值,因此很可能会发生这种情况(这似乎也是可观察到的行为)

于 2012-04-23T10:07:37.977 回答
13

UIButtonSwift 中的子类

*以下代码适用于 Swift 3 及更高版本。

您不能通过设计设置buttonTypeUIButton类的。它会自动设置为custom,这意味着您将以简单的外观和行为作为起点。

如果您想重用设置按钮外观的代码,您可以在不使用子类的情况下执行此操作。一种方法是提供创建UIButton和设置视觉属性的工厂方法。

避免子类化的示例工厂方法

extension UIButton {
    static func createStandardButton() -> UIButton {
        let button = UIButton(type: UIButtonType.system)
        button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)
        button.setTitleColor(UIColor.black, for: .normal)
        button.setTitleColor(UIColor.gray, for: .highlighted)
        return button
    }
}

let button = UIButton.createStandardButton()

UIButton当其他定制技术足够时,我会避免子类化。工厂方法示例是一种选择。还有其他选项,包括 UIAppearance API 等。

有时存在需要子类化的定制需求。例如,我创建了UIButton子类来精细控制按钮如何响应触摸事件进行动画处理,或者让按钮在点击时调用预定义的委托或闭包(而不是为#selector每个实例分配 a)。

下面是一个基本的UIButton子类示例作为起点。

示例 UIButton 子类

internal class CustomButton: UIButton {

    init() {
        // The frame can be set outside of the initializer. Default to zero.
        super.init(frame: CGRect.zero)
        initialize()
    }

    required init?(coder aDecoder: NSCoder) {
        // Called when instantiating from storyboard or nib
        super.init(coder: aDecoder)
        initialize()
    }

    func initialize() {
        print("Execute common initialization code")
    }
}

let button = CustomButton()
print(button.buttonType == .custom)  // true

 

关于UIButtonType

自 2012 年提出该问题以来,该问题UIButtonType.roundedRect已被弃用。头文件注释说要UIButtonType.system改用。

以下是从 UIButton.h 在 Xcode 中转换为 Swift

public enum UIButtonType : Int {

    case custom // no button type

    @available(iOS 7.0, *)
    case system // standard system button

    case detailDisclosure
    case infoLight
    case infoDark
    case contactAdd

    public static var roundedRect: UIButtonType { get } // Deprecated, use UIButtonTypeSystem instead
}
于 2017-02-17T23:10:03.400 回答
12

不是你要找的东西,但请记住,你的子类仍然有 buttonWithType 方法,它工作正常。

buttonWithType 调用您的子类 initWithFrame,并适当地设置类型。

SubclassButton *myButton=[SubclassButton buttonWithType:UIButtonTypeRoundedRect];
于 2013-09-12T16:26:29.580 回答
2

创建一个方便的 init 对我有用:

class CustomButton: UIButton {
    
    convenience init() {
        self.init(type: .system)
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        /*Do customization here*/
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        
        /*Do customization here*/
    }
}
于 2021-07-30T17:59:12.343 回答
1

对于 iOS7,这比以前更相关,因为有时您需要使用 UIButtonTypeSystem,并且您不能简单地覆盖 init 并执行 [MyButton alloc] init],因为它是一个 UIButtonTypeCustom,它不反映 tintColor 也没有 nice突出淡化效果。

要子类化,请像这样创建一个静态构造函数:

+ (instancetype)myButtonWithTitle:(NSString *)title imageNamed:(NSString *)imageName target:(id)target action:(SEL)action {
    MyButton *button = [self buttonWithType:UIButtonTypeSystem];
    ... my custom setup for title, image, target, etc ...
    return button;
}
于 2014-05-30T03:52:44.493 回答
1

这不是一个好的解决方案,所以我们需要“感谢”苹果使用这个拐杖。XD

//if self.buttonType == .system && self.state.contains(.highlighted) {
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
        self.titleLabel?.alpha = 1.0
    }
//}

touchesBegan(...)例如添加。

于 2020-06-10T15:38:17.367 回答
0

你绝对可以继承 UIButton。我已经成功创建了一个看起来像 UITextField 的 DateButton,但是当用户触摸它时,它会在 Popover 中显示一个 DatePicker。具有用于存储日期等的属性。如果上述方法从未解决您的问题,请告诉我,我将发布更多详细信息。

于 2013-07-14T21:46:23.847 回答
-2

那这个呢?

- (id)initWithFrame:(CGRect)frame 
{
    self = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 
    if (self) {
        self.frame = frame;
    }

    return self;
}
于 2012-04-23T09:37:37.137 回答