IPhoneのセレクターで引数を渡す
-
11-07-2019 - |
質問
アニメーションブロックの2つのビューを交換するアクションを呼び出すbarButtonItemがあります。呼び出すアクションメソッドの先頭で barButtonItem
を無効にし、完了時に有効にしたいので、ユーザーはビューが反転を完了する前に再び反転できないようにします。
これはUIViewアニメーションブロックで行うため、メソッドのnedで有効にすると、すぐに有効になり、アニメーションが終了する前に有効になるため、目的が破壊されます。
このメソッドでは、送信者をUIBarButtonItemにキャストし、それを無効にします。だから [UIView setAnimationDidStopSelector:@selector()]
を見つけましたが、セレクタにbarButtonItemを渡す必要があるので、enableControlメソッドでそれを有効にします(匿名にすることができればもっと簡単になります)関数..)。
では、どのように引数としてbarButtonを渡すことができますか?これだけのためにivarを作成する必要はありません。コードは次のとおりです。
- (void)barBtnItemSwitchViews_Clicked:(id)sender {
UIBarButtonItem *barButton = (UIBarButtonItem *)sender;
barButton.enabled = NO;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.8];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
if(!self.yellowVC.view.superview) {
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:innerView cache:YES];
[yellowVC viewWillAppear:YES];
[blueVC viewWillDisappear:YES];
[blueVC.view removeFromSuperview];
self.blueVC = nil;
[innerView addSubview:yellowVC.view];
} else if(!self.blueVC.view.superview) {
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:innerView cache:YES];
[blueVC viewWillAppear:YES];
[yellowVC viewWillDisappear:YES];
[yellowVC.view removeFromSuperview];
self.yellowVC = nil;
[innerView addSubview:blueVC.view];
}
[UIView commitAnimations];
[UIView setAnimationDidStopSelector:@selector(enableControl:)]; // How do I pass barButton??
}
- (void)enableControl:(UIControl *)control {
control.enabled = YES;
}
変更したものを次に示しますが、メソッドは呼び出されていません。何が間違っていますか
- (void)barBtnItemSwitchViews_Clicked:(id)sender {
UIBarButtonItem *barButton = (UIBarButtonItem *)sender;
barButton.enabled = NO;
[UIView beginAnimations:nil context:barButton];
[UIView setAnimationDuration:0.8];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
if(!self.yellowVC.view.superview) {
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:innerView cache:YES];
[yellowVC viewWillAppear:YES];
[blueVC viewWillDisappear:YES];
[blueVC.view removeFromSuperview];
self.blueVC = nil;
[innerView addSubview:yellowVC.view];
} else if(!self.blueVC.view.superview) {
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:innerView cache:YES];
[blueVC viewWillAppear:YES];
[yellowVC viewWillDisappear:YES];
[yellowVC.view removeFromSuperview];
self.yellowVC = nil;
[innerView addSubview:blueVC.view];
}
[UIView setAnimationDidStopSelector:@selector(flipViewAnimationDidStop:finished:context:)];
[UIView commitAnimations];
}
- (void)flipViewAnimationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
UIBarButtonItem *barButton = (UIBarButtonItem *)context;
barButton.enabled = NO;
NSLog(@"Disabled");
}
編集:わかりました。ボタンをコンテキストにし、 setAnimationDelegate:self
を実行し、次に setAnimationDidEndSelector:@selector(myMethod:finished:context:)
を実行してから、メソッドでコンテキストを uibarbuttonitem
にキャストして、再度有効にします。
解決
UIViewの setAnimationDidStopSelectorから:
docs:
セレクターの形式は、
-(void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
です。
3番目の引数 context
は、選択したオブジェクトで、 beginAnimations:context:
で設定します。不足しているのは、 context
引数として barButton
を使用し、適切な署名で enableControl
を書き換えることです。このメソッドでは、3番目の引数 context
を取得し、それを void *
から UIBarButtonItem *
にキャストします。
他のヒント
@selectorを使用して複数の引数をセレクターに渡すことはできませんが、ボタンをクラス変数にして、セレクターのようにボタンを有効または無効にすることはできません(引数として渡す代わりに) 、複数の引数を持つセレクターを定義するには、NSInvocationを使用できます。
NSInvocation *inv = [[NSInvocation alloc] init];
[inv setSelector:@selector(foo:bar:)];
[inv setArgument:123 atIndex:0];
[inv setArgument:456 atIndex:1];
しかし、これはあなたがやろうとしていることに対してうまくいくとは思わない。