使用删除function创建自定义UIButton类

我有一个UIButtons网格。 当我点击“编辑”按钮时,我想在每个按钮上显示一个删除按钮,按下该按钮时,删除按钮(和相关数据)。 有点像苹果的主屏幕,当你按住一个按钮时,它开始在角落里摆动一个X。

根据这篇文章: Subclass UIButton添加一个属性我可以使用Associative References为我的每个按钮添加一个属性。 我试图添加一个UIButton作为我的自定义UIButton的属性,但我似乎无法让它出现并感觉这不是正确的方法。 这是我的自定义按钮主要:

#import "UIButton+Property.h" #import  @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 

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

 //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]; } 

有没有更容易更明智的方法来做到这一点? 还是我走在正确的轨道上?

原始回应开始:

……其他人可能有更多话要说,但我不确定你为什么需要在这里使用对象关联。 您当然可以使用常规子类化向您的按钮添加另一个按钮作为属性,这是我将采取的路径。 …

以下编辑:

我以为我直接将子控件子类化了,但是当我去寻找代码时,我意识到自己错了。 @Joe在评论中正确地指出直接子类化UI控件存在问题。

通过创建一个包装类来保存按钮及其相关的删除按钮,我能够实现类似于您所描述的function而不使用关联对象。 它有效,但它不是很灵活,所以我一般会推荐@ Joe的方法作为更好的解决方案。

这是相关的代码:

我把所有代码都放到appDelegate中以保持简单。 我不建议在现实生活中。

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:

 @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属性,但它确实需要额外的工作来挂钩嵌入的委托,这很麻烦。 可能有一种方法可以在初始化时将委托传递给包装器,但我无法使其工作。