Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

ターゲット/アクションデザインパターン

Tatsuro Ueda edited this page · 5 revisions

ボタンを押したら画面が切り替わるというパターンは多い。

このとき、押されたボタン自身に画面を切り替える機能を持たせるより、 ボタンにはボタンが押されたという通知だけおこなわせ、 画面の切り替えは通知を受けた側が担当した方が汎用性がある。

このようなパターンを「ターゲット/アクションパターンデザイン」と呼ぶ。

簡単な例

#import <UIKit/UIKit.h>
@interface Button : UIView
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
@end
@implementation Button

...

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"touched");
}

ビューコントローラのStoryboard上にUIViewを貼り、ボタンくらいの大きさにし、色を付け、クラスをButtonクラス、インスタンス名をbuttonにする(self.buttonで参照できる)。

#import <UIKit/UIKit.h>
#import "Button.h"
@interface ViewController : UIViewController
@property (weak, nonatomic) IBOutlet Button *button;
@end

実行すると画面にButtonが表示され、タップするとコンソールに"touched"と出力される。

ボタンがビューコントローラのメソッドを蹴るようにする

次に、ButtonがtargetのViewControllerクラスのtouchedメソッドを蹴るようにする。

@protocol ButtonPerformer
- (void)touched;
@end

@interface Button : UIView
@property id<ButtonPerformer> target;
@end

@implementation Button : UIView

...

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [target touched]
}
@end

蹴られるViewControllerクラス:

#import <UIKit/UIKit.h>
#import "Button.h"

@interface ViewController : UIViewController<ButtonPerformer>
@property (weak, nonatomic) IBOutlet Button *button;
@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    button.target = self;
}

- (void)touched
{
    self.view.backgroundColor = [UIColor greenColor];
}

@end

さらに汎用的にする

現状ではButtonのtargetに設定するオブジェクトは、必ず-touchedメソッドが必要になるなど、汎用性に欠ける。

どんなメソッドでも大丈夫なように変える。

NSObjectクラスの-performSelector:withObject:を使う。

ボタンクラス:

@interface Button : UIView
@property id target;
@property SEL action;
@end

@implementation Button

...

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [target performSelector:action withObject:self];
}

@end

ビューコントローラクラス:


...

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    button.target = self;
    button.action = @selector(printConsole);
}

- (void)printConsole
{
    NSLog(@"touched");
}

@end
...
Something went wrong with that request. Please try again.