我有一个UIButtons网格。当我点击“编辑”按钮时,我想在每个按钮上显示一个删除按钮,按下该按钮时,删除按钮(和相关数据)。有点像苹果的主屏幕,当你按住一个按钮,它开始在拐角处摆动一个X。
根据这篇文章:Subclass UIButton to add a property我可以使用关联引用为我的每个按钮添加属性。我试图添加一个UIButton作为我的自定义UIButton的属性,但我似乎无法让它出现并感觉这不是正确的方法。这是我的自定义按钮主页:
#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
这是我以编程方式添加按钮的地方:
//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];
}
有更容易更合理的方法吗?还是我走在正确的轨道上?
答案 0 :(得分:1)
原始回应开始:
......其他人可能有更多话要说,但我不确定为什么你需要在这里使用对象关联。您当然可以使用常规子类化向您的按钮添加另一个按钮作为属性,这是我将采取的路径。 ...
以下编辑:
我认为我直接将UI控件子类化了,但是当我去寻找代码时,我意识到自己错了。 @Joe在评论中正确指出直接子类化UI控件存在问题。
通过创建一个包装类来保存按钮及其相关的删除按钮,我能够实现类似于您所描述的功能而不使用关联对象。它有效,但它不是很灵活,所以我一般会推荐@ 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属性,但它确实需要额外的工作来连接嵌入的委托,这很麻烦。可能有一种方法可以在初始化时将委托传递给包装器,但我无法使其工作。