使用删除功能创建自定义UIButton类 [英] Create a custom UIButton class with delete function

查看:52
本文介绍了使用删除功能创建自定义UIButton类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个UIButtons网格.当我点击编辑"按钮时,我希望在这些按钮的每个上方都显示一个删除按钮,按下该按钮会删除该按钮(及相关数据).有点像苹果的主屏幕,当您按住一个按钮时,它开始在拐角处摆动一个X.

I have a grid of UIButtons. When I hit an 'edit' button, I want a delete button to appear over each of these buttons, which when pressed, deletes the button (and associated data). A bit like apple's home screen, when you hold down a button and it starts to wiggle with an X in the corner.

根据这篇文章:子类UIButton来添加属性使用关联引用将属性添加到我的每个按钮.我尝试将UIButton添加为自定义UIButton的属性,但似乎无法使其显示并感觉这不是正确的方法.这是我的自定义按钮主要:

According to this post: Subclass UIButton to add a property I can use Associative References to add a property to each of my buttons. I've tried to add a UIButton as a property of my custom UIButton but I can't seem to get it to appear and have the feeling this isn't the right way to go. Here's my custom button main:

    #import "UIButton+Property.h"
#import <objc/runtime.h>

@implementation UIButton(Property)

static char UIB_DELETEBUTTON_KEY;

@dynamic deleteButton;


- (void)setDeleteButton:(UIButton *)deleteButton {
    deleteButton = [UIButton buttonWithType:UIButtonTypeInfoDark];
    deleteButton.frame = CGRectMake(100, 100, 50, 50);
    objc_setAssociatedObject(self, &UIB_DELETEBUTTON_KEY, deleteButton, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (UIButton *)deleteButton {
    return (UIButton *)objc_getAssociatedObject(self, &UIB_DELETEBUTTON_KEY);
}

@end

这是我以编程方式添加按钮的地方:

And here's where I add the buttons programmatically:

//Create a custom button for each custom book doc
for (int i = 0; i < [customBookDocs count]; ++i) {
    BookDoc *customBookDoc = [customBookDocs objectAtIndex:i];
    NSString *bookTitle = customBookDoc.book.title;

    //create a button for each book
    CGRect frame = CGRectMake(xCoord, yCoord, 200, 200);
    UIButton *bookButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    bookButton.bookDoc = customBookDoc;
    [bookButton setFrame:frame];
    [bookButton setTitle:bookTitle forState:UIControlStateNormal];
    [bookButton addTarget:self action:@selector(bookButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
    xCoord += 250;

    [self.view addSubview:bookButton];
    [self.view addSubview:bookButton.deleteButton];
}

是否有更简单,更明智的方法来做到这一点?还是我在正确的轨道上?

Is there an easier more sensible way to do this? Or am I on the right track?

推荐答案

原始响应开始:

...可能还有其他人要说,但是我不确定为什么需要在这里使用对象关联.当然,您可以使用常规子类将另一个按钮作为属性添加到按钮中,这就是我要采取的途径....

... Someone else may have more to say about that, but I'm not sure why you'd need to use object association here. You can certainly add another button to your button as a property using regular subclassing, which is the route that I would take. ...

以下

我认为我已经直接将UI控件子类化了,但是我意识到在去查找代码时我弄错了.@Joe在评论中正确指出,直接继承UI控件存在问题.

I thought that I had subclassed a UI control directly, but I realized that I was mistaken when I went to look for the code. @Joe rightly pointed out in the comments that there are issues with directly subclassing UI controls.

通过创建包装器类来保存按钮及其相关的删除按钮,我能够在不使用关联对象的情况下实现类似您所描述的功能.它可以工作,但不是很灵活,因此我通常建议使用@Joe的方法作为更好的解决方案.

I was able to implement something like the functionality you described without using Associated Objects, by creating a wrapper class to hold the button and its related delete button. It works, but it's not very flexible, so I would generally recommend @Joe's method as a better solution.

以下是相关代码:

我将所有代码都放入了appDelegate中,以使其保持简单.在现实生活中,我不建议这样做.

I threw all of the code into the appDelegate to keep it simple. I don't recommend that in real life.

AppDelegate.m:

AppDelegate.m:

@implementation AppDelegate

@synthesize window = _window;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    self.window.backgroundColor = [UIColor whiteColor];

    UIButton *toggleDeleteButtons = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [toggleDeleteButtons setFrame:CGRectMake(20, 45, 280, 45)];
    [toggleDeleteButtons setTitle:@"Toggle Delete" forState:UIControlStateNormal];
    [toggleDeleteButtons addTarget:self action:@selector(toggleDeleteButtonAction) forControlEvents:UIControlEventTouchUpInside];
    [[self window] addSubview:toggleDeleteButtons];

    ButtonWrapper *myButtonWrapper = [[ButtonWrapper alloc] init];
    [[myButtonWrapper button] setFrame:CGRectMake(20, 100, 200, 45)];
    [[myButtonWrapper button] setTitle:@"This is my button" forState:UIControlStateNormal];
    [[myButtonWrapper deleteButton] addTarget:self action:@selector(buttonDeleteRequested:) forControlEvents:UIControlEventTouchUpInside];
    [[myButtonWrapper deleteButton] setTag:0];
    [[self window] addSubview:[myButtonWrapper button]];
    buttonWrapper1 = myButtonWrapper;

    // Added instance called anotherButtonWrapper with tag 1, as above

    // Added instance called stillAnotherButtonWrapper with tag 2, as above

    [self.window makeKeyAndVisible];
    return YES;
}

- (void)toggleDeleteButtonAction {
    static BOOL deleteButtonsShown;

    [buttonWrapper1 showDeleteButton:!deleteButtonsShown];
    [buttonWrapper2 showDeleteButton:!deleteButtonsShown];
    [buttonWrapper3 showDeleteButton:!deleteButtonsShown];
    deleteButtonsShown = !deleteButtonsShown;
}

- (void)buttonDeleteRequested:(UIButton *)deleteButton {
    // delete the specified button here
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Delete" message:[NSString stringWithFormat:@"Delete was pressed on button %i",[deleteButton tag]]delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
    [alert show];
}

ButtonWrapper.m:

ButtonWrapper.m:

@implementation ButtonWrapper

@synthesize button;
@synthesize deleteButton;

- (ButtonWrapper *)init {
    ButtonWrapper *newWrapper = [ButtonWrapper alloc];

    UIButton *myButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [myButton setFrame:CGRectZero];

    UIButton *myDeleteButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [myDeleteButton setFrame:CGRectMake(0, 0, 100, 40)];
    [myDeleteButton setTitle:@"Delete" forState:UIControlStateNormal];
    [myDeleteButton setHidden:TRUE];
    [myButton addSubview:myDeleteButton];

    [newWrapper setButton:myButton];
    [newWrapper setDeleteButton:myDeleteButton];

    return newWrapper;
}

- (void)showDeleteButton:(BOOL)showButton {
    if (showButton) {
        [[self deleteButton] setHidden:FALSE];
        [[self deleteButton] setEnabled:TRUE];    }
    else {
        [[self deleteButton] setHidden:TRUE];
        [[self deleteButton] setEnabled:FALSE];
    }
}
@end

此解决方案不需要我实现所有UI属性,但是确实需要额外的工作来连接嵌入式委托,这很麻烦.可能有一种在初始化时将委托传递给包装器的方法,但我无法使其工作.

This solution did not require me to implement all of the UI properties, but it did require extra work to hook up the embedded delegates, which is cumbersome. There may be a way to pass the delegates into the wrapper at initialization, but I couldn't make it work.

这篇关于使用删除功能创建自定义UIButton类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆