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:) .....];