2012/2/14 コードの部分を修正しました。
iPhoneアプリ開発で画像をタッチしたりホールドしたらアクションをおこしたい・・
って場合はあると思います。
そのメモです。ざっくりです。
コーディングのポイント
タッチとホールドを実現するのにキーとなるコードは以下の通り。
これだけわかれば組めるはず。
UIImageViewのタッチを有効にします。
(self = UIImageView)
// タッチイベントを許可する
self.userInteractionEnabled = YES;
// マルチタッチを有効にする。
[self setMultipleTouchEnabled:YES];
すると、以下の3つのタッチイベントが有効になります。
// タッチした時に呼ばれるアクション
– (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
// タッチ離した時に呼ばれるアクション
– (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
ホールドはNSTimerを使って実現します。
[NSTimer scheduledTimerWithTimeInterval:delay target:self selector:@selector(touchesHold:withEvent:) userInfo:nil repeats:NO];
実際のコード
妖精の画像をタッチしたりホールドするとアクションがおこしたかった。
妖精をUIImageViewを継承してFairyクラスとしてます。
#import <Foundation/Foundation.h> @interface TestImageView : UIImageView { NSTimer *touchTimer; } @end
@implementation TestImageView - (void)viewDidLoad { [super viewDidLoad]; //タッチイベントを許可する self.userInteractionEnabled = YES; [self setMultipleTouchEnabled:YES]; } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { NSLog(@"タッチイベント開始"); /** * NSTimerでホールド処理を呼び出す * ホールド中に処理を繰り返すならrepeatsをYES、そうでなければNO * ホールドの座標を使用したい場合はUserInfoにtouchesを渡す */ touchTimer = [NSTimer scheduledTimerWithTimeInterval:0.8 target:self selector:@selector(touchesHold:) userInfo:touches repeats:YES]; [touchTimer retain]; } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { NSLog(@"タッチイベント終了"); if ([touchTimer isValid]) [touchTimer invalidate]; } - (void)touchesHold:(NSTimer *)timer { NSLog(@"タッチホールド"); /** * ここにホールド時の処理を書く * 下記は一例です。(ホールド中に画像が拡大して飛び出ててきます) */ // userInfoを取得 NSSet *touches = [timer userInfo]; // 座標の取得 UITouch *aTouch = [touches anyObject]; CGPoint point = [aTouch locationInView:self.view]; // Imageオブジェクトを生成 NSString *imgName = [[NSString alloc] initWithFormat:@"popupImageSample.gif"]; UIImageView *iv = [[UIImageView alloc] initWithImage:[UIImage imageNamed:imgName]]; [self.view addSubview:iv]; iv.frame = CGRectMake(0, 0, 30, 30); iv.center = CGPointMake(point.x, point.y); iv.alpha = 0.8; // アニメーション処理実装 [UIView beginAnimations:nil context:nil]; [UIView setAnimationDuration:1.0]; [UIView setAnimationDelay:0.0]; [UIView setAnimationRepeatCount:1.0]; [UIView setAnimationCurve:UIViewAnimationCurveEaseIn]; [UIView setAnimationDelegate:self]; iv.transform = CGAffineTransformMakeScale(300, 300); iv.alpha = 0.0; [UIView commitAnimations]; // アニメーション終了後にオブジェクトをリリースする [self performSelector:@selector(animationStopped:) withObject:iv afterDelay:1.0]; [imgName release]; } /** * アニメーション停止後の処理 */ - (void)animationStopped:(UIImageView *)ivv { NSLog(@"画像をリリースします"); [ivv removeFromSuperview]; [ivv release]; ivv = NULL; }
はまったポイント
下記のエラーにはまりました。
touchesHoldメソッドは存在するのに、見つかりませんよと怒られる。
*** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘-[UIImageView touchesHold:]: unrecognized selector sent to instance 0x4e22670’
解決法がわかると、ほんと大した事なくて凹むのですが・・・。
ただのセレクタの表記ミスでした。
しっかり引数もつけてあげましょう。
(誤) [NSTimer …. selector:@selector(touchesHold:) …..];
(正) [NSTimer …. selector:@selector(touchesHold:withEvent:) …..];