2012-04-17 5 views
2

У меня есть сетка UIButtons. Когда я нажимаю кнопку «Изменить», я хочу, чтобы на каждой из этих кнопок появилась кнопка удаления, которая при нажатии удаляет кнопку (и связанные с ней данные). Немного похоже на домашний экран Apple, когда вы удерживаете кнопку, и она начинает шевелить с помощью X в углу.Создайте пользовательский класс UIButton с функцией удаления

В соответствии с этим постом: 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]; 
} 

Есть ли более простой более разумный способ сделать это? Или я на правильном пути?

+1

Вы никогда не устанавливали кнопку удаления. Также ваш ассоциативный метод просто отменяет установленную вами кнопку удаления. – Joe

ответ

1

ORIGINAL РЕАКЦИЯ НАЧАЛОСЬ:

... Кто-то может иметь больше, чтобы сказать об этом, но я не знаю, почему вы должны были бы использовать объект ассоциации здесь. Вы, безусловно, можете добавить еще одну кнопку к своей кнопке в качестве свойства, используя регулярное подклассирование, которое является тем маршрутом, который я бы взял. ...

редактирует НИЖЕ:

Я думал, что я подклассы контроля пользовательского интерфейса напрямую, но я понял, что ошибся, когда я пошел искать код. @Joe справедливо указала в комментариях, что есть проблемы с непосредственным подклассом элементов управления пользовательского интерфейса.

Я смог реализовать что-то вроде описанной вами функции без использования связанных объектов, создав класс-оболочку, чтобы удерживать кнопку и связанную с ней кнопку удаления. Он работает, но он не очень гибкий, поэтому я бы рекомендовал метод @ 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 

Это решение не требует от меня реализовать все свойства пользовательского интерфейса, но это требует дополнительной работы для подключения встроенных делегатов, что является громоздким. Может быть способ передать делегатов в оболочку при инициализации, но я не мог заставить ее работать.

+1

UIButton является частью кластера классов, поэтому ассоциативные ссылки имеют больше смысла. – Joe

+0

+1 @Joe. По этой причине я склонен подклассифицировать UIControl вместо UIButton, так как базовые кнопки настолько уродливы, что вы не теряете много, и добавить их, чтобы вернуть функциональность кнопки, не так много. – jrturton

+0

Я читал, что в общем подклассе UIButton - плохая идея и требует большого количества кода для репликации основного поведения. Вот почему я пробовал Ассоциативные ссылки, хотя я не совсем уверен, что я там делаю ... Но я мог бы вернуться к подклассу UIButton, если не могу понять. – Smikey

Смежные вопросы