2

UIButtons のグリッドがあります。「編集」ボタンを押すと、これらの各ボタンの上に削除ボタンが表示され、押すとボタン(および関連データ)が削除されます。Apple のホーム画面に少し似ています。ボタンを押したままにすると、隅に X が表示されて小刻みに動き始めます。

この投稿によると: UIButton をサブクラス化してプロパティを追加する 連想参照を使用して、各ボタンにプロパティを追加できます。カスタム 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];
}

これを行うためのより簡単で賢明な方法はありますか?それとも私は正しい軌道に乗っていますか?

4

1 に答える 1

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 プロパティを実装する必要はありませんでしたが、埋め込まれたデリゲートを接続するために余分な作業が必要になり、面倒でした。初期化時にデリゲートをラッパーに渡す方法があるかもしれませんが、機能させることができませんでした。

于 2012-04-17T15:28:36.127 に答える