5

を含むUIViewControllerwithがUIViewありますUIButtonUIViewControllerボタンクリックイベントでメソッドをトリガーしたい。
次のリンクにあるように、の参照を維持UIViewControllerすることは良い考えではないようです 。UIViewからUIViewControllerにアクセスしますか?

ですから、デリゲートを使用してこれを達成したいと思います。これを達成する方法についてのヒントはありますか?

4

7 に答える 7

9

あなたはこのようなことをすることができます

CustomView.h

#import <UIKit/UIKit.h>
@protocol CustomViewDelegate <NSObject>

 -(void)didButtonPressed;

@end

 @interface CustomView : UIView

  @property (assign) id<CustomViewDelegate> delegate;

@end

CustomView.m

#import "CustomView.h"
@implementation CustomView

- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
    // Initialization code
    self.backgroundColor = [UIColor whiteColor];

    //[self addSubview:titleLbl];
    UIButton *button= [UIButton buttonWithType:UIButtonTypeRoundedRect];
    button.frame = CGRectMake(100, 100, 100, 50);
    [button addTarget:self.delegate action:@selector(didButtonPressed) forControlEvents:UIControlEventTouchUpInside];
    [button setTitle:@"pressMe" forState:UIControlStateNormal];
    [self addSubview:button];


}
return self;
}

ViewController.m

-(void)loadView
 {
  [super loadView];
  CustomView *view = [[CustomView alloc]initWithFrame:self.view.bounds];
  view.delegate = self;
  [self.view addSubview:view];

 }
于 2013-03-12T14:14:05.577 に答える
3

これがレスポンダーチェーンの目的です。ボタンにターゲットを追加するときは、ターゲットを指定するだけnilです。

[mySpecialButton addTarget:nil 
                 action:@selector(mySpecialButtonTapped:)
                 forControlEvents:UIControlEventTouchUpInside];

ターゲットとは、nil基本的に「mySpecialButtonTapped:レスポンダーチェーン内でそれを処理できるオブジェクトに送信する」ことを意味します。

これで、このセレクターをレスポンダーチェーンのどこでも処理できます。これには、ボタン自体、そのビューを含む、ビューコントローラーを含む、UIApplication、そして最後にAppDelegateが含まれます。このメソッドを、ニーズに最も適したオブジェクトに配置するだけです。

- (void)mySpecialButtonTapped:(id)sender {
    NSLog("My special button was tapped!");
}

メッセージをバブルアップしたいだけの場合は、デリゲートやコールバックブロック(受け入れられた回答のように)は必要ありません。

于 2015-08-28T20:02:13.077 に答える
1

コントローラーにボタンアクションを渡すだけで、もっと基本的なことを期待していたと思います。モデル/ビュー/コントローラーのコラボレーションの場合、私は常にMVCパターンに従います。それはあなたの問題と他の多くを解決します。そして、私の経験を共有したいと思います。

  1. コントローラをビューおよびモデルから分離します。すべての「ビジネスロジック」をビュー関連のクラスに入れないでください。これにより、コードが非常に使用できなくなります。このコードをホストするコントローラークラスを作成しますが、コントローラークラスがプレゼンテーションについてあまり多くの仮定をしないようにします。
  2. すべてのメソッドが必要でない場合は@protocol、を使用してコールバックAPIを定義します。@optional
  3. <view class name>Protocolビューの場合は、 (NewsViewProtocolの例)のようなプロトコルを定義します。コントローラの場合、デリゲートのように定義し<view class name>Delegate(例NewsViewDelegate)、dataSourceのように定義します<view class name>DataSource(例NewsViewDataSource)。<view class name>Protocol.hこのすべての@protocolsを(NewsViewProtocol.hの例)という名前の1つの別個のファイルに保持します。

簡単な例:

NewsView.hの内容

//
// NewsView.h
@interface NewsView : UIView <NewsViewProtocol> {
@protected
     NSObject* delegate_;
     NSObject* dataSource_;
}
@end

NewsController.hおよび.mの内容

//
// NewsController.h
@interface NewsController : UIViewController <NewsViewDataSource, NewsViewDelegate> {
}
@property (nonatomic, weak) UIView<NewsViewProtocol>* customView;
@end

@implementation NewsController
- (void)viewDidLoad {
    [super viewDidLoad];
    self.customView = (UIView<NewsViewProtocol>*)self.view;
    [self.customView setDelegate:self];
    [self.customView setDataSource:self];
}
@end

NewsViewProtocol.hの内容

//
// NewsViewProtocol.h
@protocol NewsViewProtocol;

@protocol NewsViewDelegate<NSObject>
@optional
- (void)someAction;
- (void)newsView:(UIView<NewsViewProtocol>*)newsView didSelectItemAtIndexPath:(NSIndexPath *)indexPath;
@end

@protocol NewsViewDataSource<NSObject>
@required
- (id)newsView:(UIView<NewsViewProtocol>*)newsView itemAtIndexPath:(NSIndexPath *)indexPath;
- (NSInteger)numberOfItemsInNewsView:(UIView<NewsViewProtocol>*)newsView section:(NSInteger)section;
- (BOOL)newsView:(UIView<NewsViewProtocol>*)newsView shouldDisplaySection:(NSInteger)section;
@end

@protocol NewsViewProtocol<NSObject>
@required

//Never retain delegate instance into implementation of this method
- (void)setDelegate:(NSObject<NewsViewDelegate>*)delegate;
//Never retain delegate instance into implementation of this method
- (void)setDataSource:(NSObject<NewsViewDataSource>*)dataSource;
- (void)reload;
@end

あなたはそれが冗長であると考えるかもしれません。シンプルビューコントローラーでは、はい。ただし、大量のデータを含む非常に複雑な画面を開発する場合は、次のようないくつかの利点があります。

  • ビューとコントローラーの間で責任を分離するのに役立ちます。
  • コードを明確に保ちます。
  • コードをより再利用可能にします。
于 2013-03-12T14:36:59.343 に答える
0

xCodeでの生活は簡単です。

最初に、xibビュー(ボタンが内部にあるビュー)が正しいViewControllerクラスに関連付けられていることを確認してください。これは、新しいプロジェクトまたはカスタムプロジェクトに付属するデフォルトのViewControllerクラスにすることができます。

この後、魔法のトリックがやってくる!ビューを2つのパネルに分割します。目標は、xibとviewControllerコード(.mファイル)を確認することです。次に、キーボードのコントロールキーを押して、UIButtonをコードにドラッグします。IBActionを選択します。それはあなたが他の言語で「リスナー」と呼ぶことができる何かを生成します。View Controllerのコアコードに移動し、メソッドを完了します。

そんなに簡単!楽しむ :)

于 2013-03-12T12:44:57.597 に答える
-1

プログラムでボタンを追加するには、myViewController.mで

UIView *yourView = [[UIView alloc] init];
UIButton *yourButton = [[UIButton alloc] initWithFrame:CGRectMake(0,0,100,21)];
[yourButton addTarget:self action:@selector(yourMethod) forControlEvents:UIControlEventTouchDown];
[yourView addSubview:yourButton];

詳細はこちら

于 2013-03-12T13:04:20.843 に答える
-1

このためにデリゲートは実際には必要ありません。これは、UIButtonの使用方法です。Controlキーを押しながらクリックして、ボタンからUIViewControllerの.mファイルにドラッグします。これにより、新しいメソッドが作成されます。そこから、作成したメソッドを呼び出すか、新しいメソッドに持っているものをコピーして貼り付けることができます。

于 2013-03-12T12:42:24.093 に答える
-1

あなたはこれを試すことができます:

[yourButton addTarget:self action:@selector(yourButtonAction:) forControlEvents:UIControlEventTouchUpInside];

そしてセレクターでアクションを指定します

- (IBAction)yourButtonAction:(id)sender {
     //Action to perform
}
于 2013-03-12T13:06:30.243 に答える