2012-04-17 11 views
2

私はUIButtonのグリッドを持っています。 「編集」ボタンを押すと、これらの各ボタンの上に削除ボタンが表示されます。このボタンを押すと、ボタン(および関連するデータ)が削除されます。 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

元の応答が始まりました。あなたは確かに私が取るだろうルートである通常のサブクラスを使用してプロパティとして別のボタンをボタンに追加することができます。 ...

、以下の編集:

私は私が直接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プロパティのすべてを実装するために私を必要としませんでしたが、それはフックアップするために余分な作業が必要でした組み込みの代理人は煩雑です。デリゲートを初期化時にラッパーに渡す方法があるかもしれませんが、動作させることができませんでした。

+1

UIButtonはクラスクラスタの一部であるため、関連参照はより意味があります。 – Joe

+0

+1 @Joe。基本的なボタンはあまりにも醜いので、UICuttonをUIButtonの代わりにサブクラス化する傾向があります。なぜなら、ボタンの機能を元に戻すために追加することはあまりありません。 – jrturton

+0

私はUIButtonをサブクラス化することは悪い考えであり、基本的な振る舞いを再現するには多くのコードが必要であることを読んだことがあります。だから私は、私がそこで何をやっているのか正確には分かっていないのに、連想参照を試みたのです...しかし、私がそれを理解できなければ、UIButtonのサブクラス化に戻ることができます。 – Smikey

関連する問題