私はこのようにaddTarget:action:forControlEventsを使用しています:
[newsButton addTarget:self
action:@selector(switchToNewsDetails)
forControlEvents:UIControlEventTouchUpInside];
そして、セレクター "switchToNewsDetails"にパラメーターを渡したいです。私がやることに成功する唯一のことは、(id)senderを書くことで渡すことです:
action:@selector(switchToNewsDetails:)
しかし、整数値のような変数を渡そうとしています。このように書いてもうまくいきません:
int i = 0;
[newsButton addTarget:self
action:@selector(switchToNewsDetails:i)
forControlEvents:UIControlEventTouchUpInside];
このように書いてもうまくいきません:
int i = 0;
[newsButton addTarget:self
action:@selector(switchToNewsDetails:i:)
forControlEvents:UIControlEventTouchUpInside];
助けていただければ幸いです:)
action:@selector(switchToNewsDetails:)
ここではパラメータをswitchToNewsDetails:
メソッドに渡しません。特定のアクションが発生したときにボタンを呼び出せるようにするセレクターを作成するだけです(場合によっては修正します)。コントロールは、アクションに応答するために3種類のセレクターを使用できます。これらはすべて、パラメーターの定義済みの意味を持っています。
パラメータなし
action:@selector(switchToNewsDetails)
メッセージを送信するコントロールを示す1つのパラメーター
action:@selector(switchToNewsDetails:)
メッセージを送信するコントロールと、メッセージをトリガーしたイベントを示す2つのパラメーター:
action:@selector(switchToNewsDetails:event:)
何をしようとしているかは明確ではありませんが、特定の詳細インデックスを各ボタンに割り当てたい場合は、次のことができます。
switchToNewsDetails:
メソッドでは、そのインデックスを取得して適切な詳細を開くことができます。
- (void)switchToNewsDetails:(UIButton*)sender{
[self openDetails:sender.tag];
// Or place opening logic right here
}
ボタンのクリックとともにカスタムパラメータを渡すには、SUBCLASS UIButtonにするだけです。
(ASRがオンになっているため、コードにリリースはありません。)
これはmyButton.hです
#import <UIKit/UIKit.h>
@interface myButton : UIButton {
id userData;
}
@property (nonatomic, readwrite, retain) id userData;
@end
これはmyButton.mです
#import "myButton.h"
@implementation myButton
@synthesize userData;
@end
使用法:
myButton *bt = [myButton buttonWithType:UIButtonTypeCustom];
[bt setFrame:CGRectMake(0,0, 100, 100)];
[bt setExclusiveTouch:NO];
[bt setUserData:**(insert user data here)**];
[bt addTarget:self action:@selector(touchUpHandler:) forControlEvents:UIControlEventTouchUpInside];
[view addSubview:bt];
受信機能:
- (void) touchUpHandler:(myButton *)sender {
id userData = sender.userData;
}
上記のコードのどの部分についても具体的に説明する必要がある場合は、コメントでお気軽にお問い合わせください。
Target-Actionでは、3種類のアクションセレクターを使用できます。
- (void)action
- (void)action:(id)sender
- (void)action:(id)sender forEvent:(UIEvent *)event
(CALayers keyValue dictにアクセスすることにより)ボタンオブジェクト自体に必要なデータを渡すことができます。
このようにターゲットを設定します(「:」を使用)
[myButton addTarget:self action:@selector(buttonTap:) forControlEvents:UIControlEventTouchUpInside];
次のように、ボタン自体にデータを追加します(ボタンの.layer
も同じです)。
NSString *dataIWantToPass = @"this is my data";//can be anything, doesn't have to be NSString
[myButton.layer setValue:dataIWantToPass forKey:@"anyKey"];//you can set as many of these as you'd like too!
次に、ボタンをタップすると、次のようにチェックできます。
-(void)buttonTap:(UIButton*)sender{
NSString *dataThatWasPassed = (NSString *)[sender.layer valueForKey:@"anyKey"];
NSLog(@"My passed-thru data was: %@", dataThatWasPassed);
}
上記の情報に一部基づいてソリューションを作成しました。 titlelabel.textに渡す文字列を設定し、titlelabel.hidden = YESに設定するだけです
このような :
UIButton *imageclick = [[UIButton buttonWithType:UIButtonTypeCustom] retain];
imageclick.frame = photoframe;
imageclick.titleLabel.text = [NSString stringWithFormat:@"%@.%@", ti.mediaImage, ti.mediaExtension];
imageclick.titleLabel.hidden = YES;
このように、継承またはカテゴリの必要はなく、メモリリークもありません。
配列内の電話番号ごとにいくつかのボタンを作成していたため、各ボタンを呼び出すには異なる電話番号が必要でした。 forループ内でいくつかのボタンを作成するときに、setTag関数を使用しました。
for (NSInteger i = 0; i < _phoneNumbers.count; i++) {
UIButton *phoneButton = [[UIButton alloc] initWithFrame:someFrame];
[phoneButton setTitle:_phoneNumbers[i] forState:UIControlStateNormal];
[phoneButton setTag:i];
[phoneButton addTarget:self
action:@selector(call:)
forControlEvents:UIControlEventTouchUpInside];
}
次に、call:メソッドで、同じforループとifステートメントを使用して正しい電話番号を選択しました。
- (void)call:(UIButton *)sender
{
for (NSInteger i = 0; i < _phoneNumbers.count; i++) {
if (sender.tag == i) {
NSString *callString = [NSString stringWithFormat:@"telprompt://%@", _phoneNumbers[i]];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:callString]];
}
}
}
ボタンが押されたセルのindexPathを取得できるもう1つの方法があります。
次のような通常のアクションセレクタを使用します。
UIButton *btn = ....;
[btn addTarget:self action:@selector(yourFunction:) forControlEvents:UIControlEventTouchUpInside];
そして、あなたの関数で:
- (void) yourFunction:(id)sender {
UIButton *button = sender;
CGPoint center = button.center;
CGPoint rootViewPoint = [button.superview convertPoint:center toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:rootViewPoint];
//the rest of your code goes here
..
}
indexPathを取得するため、はるかに簡単になりました。
ソリューションについてはここで言及されている多くの方法がありますが、カテゴリ機能は除きます。
カテゴリー機能を使用して、定義済み(組み込み)要素をカスタマイズ可能な要素に拡張します。
例えば(ex):
@interface UIButton (myData)
@property (strong, nonatomic) id btnData;
@end
ビューController.mで
#import "UIButton+myAppLists.h"
UIButton *myButton = // btn intialisation....
[myButton set btnData:@"my own Data"];
[myButton addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
イベントハンドラー:
-(void)buttonClicked : (UIButton*)sender{
NSLog(@"my Data %@", sender. btnData);
}
Target-actionをクロージャー(Objective-Cのブロック)に置き換えるには、ヘルパークロージャーラッパー(ClosureSleeve)を追加し、関連付けられたオブジェクトとしてコントロールに追加して保持します。これにより、任意のパラメーターを渡すことができます。
class ClosureSleeve {
let closure: () -> ()
init(attachTo: AnyObject, closure: @escaping () -> ()) {
self.closure = closure
objc_setAssociatedObject(attachTo, "[\(arc4random())]", self, .OBJC_ASSOCIATION_RETAIN)
}
@objc func invoke() {
closure()
}
}
extension UIControl {
func addAction(for controlEvents: UIControlEvents, action: @escaping () -> ()) {
let sleeve = ClosureSleeve(attachTo: self, closure: action)
addTarget(sleeve, action: #selector(ClosureSleeve.invoke), for: controlEvents)
}
}
使用法:
button.addAction(for: .touchUpInside) {
self.switchToNewsDetails(parameter: i)
}
これは私の問題を修正しましたが、変更しない限りクラッシュしました
action:@selector(switchToNewsDetails:event:)
に
action:@selector(switchToNewsDetails: forEvent:)
上記の私のコメントを参照してください。複数のパラメーターがある場合はNSInvocationを使用する必要があると思います
nSInvocationの詳細はこちら
http://cocoawithlove.com/2008/03/construct-nsinvocation-for-any-message.html
ナビゲーションコントローラーによって新しいビューと一緒に表示されるleftBarButtonItemのテキストを変更する場合は、pushViewControllerを呼び出す直前に現在のビューのタイトルを変更して、希望するテキストに変更し、現在のビュー。
このアプローチは、機能(popViewController)と表示される矢印の外観をそのまま保持します。
Xcode 10.1でビルドされたiOS 12では少なくとも機能します...
CustomButtonでUIButtonをサブクラス化し、データを保存するプロパティを追加します。だから私はメソッドを呼び出します:(CustomButton *)senderそしてメソッドでは自分のデータsender.mypropertyを読むだけです。
CustomButtonの例:
@interface CustomButton : UIButton
@property(nonatomic, retain) NSString *textShare;
@end
メソッドアクション:
+ (void) share: (CustomButton*) sender
{
NSString *text = sender.textShare;
//your work…
}
アクションを割り当てる
CustomButton *btn = [[CustomButton alloc] initWithFrame: CGRectMake(margin, margin, 60, 60)];
// other setup…
btnWa.textShare = @"my text";
[btn addTarget: self action: @selector(shareWhatsapp:) forControlEvents: UIControlEventTouchUpInside];