如何为控件指定名称并在事件方法中检索它?

时间:2021-10-17 15:30:42

I have a IBAction such as:

我有一个IBAction,如:

- (IBAction)showPicker:(id)sender;

How can I get the name of the control from the sender variable?

如何从sender变量中获取控件的名称?

I am typically a c# coder so have tried the following to no avail

我通常是一个c#编码器,所以尝试了以下无济于事

senderName = ((UIButton *)sender).name;

I need something more descriptive than the control id (not the button title either). I have 5 buttons all calling the same method. I need to determine which was clicked in order to perform the methods actions on the appropriate control. I.E I have an address picker method but want to populate 5 text fields with different details with each of 5 buttons. Just trying to keep the code tidy

我需要一些比控件ID更具描述性的东西(也不是按钮标题)。我有5个按钮都调用相同的方法。我需要确定单击哪个以便在适当的控件上执行方法操作。 I.E我有一个地址选择器方法,但想要用5个按钮中的每一个填充5个不同细节的文本字段。只是想保持代码整洁

N.B Originally I was planning on using the Interface Builders name field, but I've been advised (below) that this isn't available at runtime.

N.B最初我打算使用Interface Builders名称字段,但我被告知(下面)这在运行时不可用。

6 个解决方案

#1


5  

You might want to look at using the tag property. It's an integer rather than a name, but can be used to differentiate between two controls. It's inherited from UIView so any control that's sending an event should have it.

您可能希望查看使用tag属性。它是整数而不是名称,但可用于区分两个控件。它继承自UIView,因此任何发送事件的控件都应该拥有它。

It's editable in Interface Builder under View attributes.

它可以在Interface Builder下的Interface Builder中编辑。

It's a property so it can be accessed programatically with the dot notation:

它是一个属性,因此可以使用点表示法以编程方式访问它:

control.tag

Or you can convert to a string as follows:

或者您可以转换为字符串,如下所示:

[stringWithFormat:@"%d", control.tag]

#2


3  

You don't use the name of an object in Interface Builder to refer to that object; it's just there for reference. (Interface Builder will also use it as a hint for what outlets connecting to the control and actions sent by the control might be named, but only as a hint.)

您不使用Interface Builder中的对象名称来引用该对象;它只是供参考。 (Interface Builder还将使用它作为连接到控件的出口和控件发送的操作可能被命名的提示,但仅作为提示。)

Instead, you add an outlet to a controller object that you connect to the object. This lets you access the object directly at runtime from your controller without going through any look-up step.

而是将插座添加到连接到对象的控制器对象。这使您可以在运行时直接从控制器访问对象,而无需执行任何查找步骤。

Also, it sounds like you have five buttons, with five things to do, all connected to the same action method. Don't do that.

此外,听起来你有五个按钮,有五个要做的事情,都连接到同一个动作方法。不要那样做。

In Cocoa and Cocoa Touch, you shouldn't typically create an action methods "per event" and then decide what to do based on which control sent the event. The controls in Cocoa handle events themselves, and translate them into higher-level actions. So you can implement five action methods in your controller, connect each button to its appropriate action method, and never have to decide what to do based on which control sent the action.

在Cocoa和Cocoa Touch中,您通常不应该“按事件”创建操作方法,然后根据发送事件的控件决定要执行的操作。 Cocoa中的控件自己处理事件,并将它们转换为更高级别的操作。因此,您可以在控制器中实现五个操作方法,将每个按钮连接到其相应的操作方法,而不必根据发送操作的控件来决定要执行的操作。

Obviously this isn't appropriate in all cases. For example, if you have a matrix of buttons with images that change at runtime, you would probably want them all to connect to the same action and distinguish them based on their tag property. A good rule of thumb is to use different action methods when dealing with "different" things, and use the same action method and control tags when dealing with "many of the same" thing.

显然这在所有情况下都不合适。例如,如果您有一个按钮矩阵,其中的图像在运行时会发生变化,您可能希望它们全部连接到同一个动作,并根据它们的标记属性区分它们。一个好的经验法则是在处理“不同”事物时使用不同的动作方法,并在处理“许多相同”事物时使用相同的动作方法和控制标记。

#3


3  

While I agree that tag will work in many circumstances, it's a pain to work with integer tags when you have a matrix of 100 buttons that are pushable where you want to identify: (1) what was pushed and (2) what value was pushed. I found myself starting to invent row/column naming schemes with tag numbers which got out of hand.

虽然我同意标签在许多情况下都能正常工作,但是如果你有一个100个按钮的矩阵可以在你想要识别的地方使用,那么使用整数标签是很痛苦的:(1)推送的内容和(2)推送的值是什么。我发现自己开始发明行/列命名方案,标签号已经失控。

I wanted multiple controls to share the same handler, and I wanted to carefully design my UI in IB to pass name/value pairs off to a key-value store based on what was pushed.

我希望多个控件共享同一个处理程序,我想在IB中仔细设计我的UI,根据推送的内容将名称/值对传递给键值存储。

As an alternative to tags, I came up with another workaround for UISegmentedControl (it works for other controls too).

作为标签的替代品,我想出了UISegmentedControl的另一种解决方法(它也适用于其他控件)。

(1) Create a new class and sub-class UISegmentedControl. Add a string property MyCustomKey to your new class.

(1)创建一个新的类和子类UISegmentedControl。将字符串属性MyCustomKey添加到新类。

@interface CustomSegmentedControl : UISegmentedControl
@property (nonatomic, retain) NSString* myCustomKey; 
@end

(2) Back in IB, modify your UISegmentedContol instances to be instances of CustomSegmentedControl. Used the IB "User Defined Runtime Attributes" to set the value of myCustomKey using IB. KeyValueCoding will take care of the setting of the properties for you:

(2)返回IB,将UISegmentedContol实例修改为CustomSegmentedControl的实例。使用IB“用户定义的运行时属性”使用IB设置myCustomKey的值。 KeyValueCoding将为您设置属性:

如何为控件指定名称并在事件方法中检索它?

(3) Wire up all your buttons to a single IBAction.

(3)将所有按钮连接到一个IBAction。

(4) In your IBAction, you can extract the key-value pairs now by reading back your custom attribute:

(4)在您的IBAction中,您现在可以通过回读自定义属性来提取键值对:

- (IBAction)myButtonPressed:(id) sender
{
    if ([sender isKindOfClass:[CustomSegmentedControl class]] == false)
        return;

    // get the key-values from the control
    CustomSegmentedControl *control = (CustomSegmentedControl *)sender;
    NSString *key = [control valueForKey:@"myCustomKey"];
    NSNumber *value = [NSNumber numberWithInteger:[control selectedSegmentIndex]];
    NSLog(@"Pressed control %@ with a value of %@", key, value);
}

In this case I was only interested in the integer value of a segmented control, but you could get any property off the control as the value.

在这种情况下,我只对分段控件的整数值感兴趣,但您可以将任何属性作为值从控件中获取。

Hope this helps.

希望这可以帮助。

#4


2  

The name field under Interface Builder Identity is something unique to Interface Builder; I'm actually not sure exactly how it's used, but it doesn't map to a usable property, ivar or method on your actual control. Instead, use the tag property (under the View attributes) to differentiate different controls from an action method if you don't otherwise keep a reference to them as an ivar. If I'm misunderstanding you and you want the button's title, just use currentTitle instead.

Interface Builder Identity下的名称字段是Interface Builder特有的;我实际上并不确定它是如何使用的,但它并没有映射到实际控制中的可用属性,ivar或方法。相反,如果不将其作为ivar引用,则使用tag属性(在View属性下)来区分不同的控件和action方法。如果我误解你并想要按钮的标题,只需使用currentTitle。

#5


0  

If the control has a name attribute, then:

如果控件具有name属性,则:

NSString *senderName = [sender name];

This isn't something most controls have. You might want:

这不是大多数控件所具有的。你可能想要:

NSString *senderName = [sender title];

If it was an NSButton, for instance. Or as Marc says, for a UIButton, use currentTitle.

例如,如果它是NSButton。或者正如Marc所说,对于UIButton,请使用currentTitle。

#6


0  

Try:

senderTitle = [sender currentTitle];

#1


5  

You might want to look at using the tag property. It's an integer rather than a name, but can be used to differentiate between two controls. It's inherited from UIView so any control that's sending an event should have it.

您可能希望查看使用tag属性。它是整数而不是名称,但可用于区分两个控件。它继承自UIView,因此任何发送事件的控件都应该拥有它。

It's editable in Interface Builder under View attributes.

它可以在Interface Builder下的Interface Builder中编辑。

It's a property so it can be accessed programatically with the dot notation:

它是一个属性,因此可以使用点表示法以编程方式访问它:

control.tag

Or you can convert to a string as follows:

或者您可以转换为字符串,如下所示:

[stringWithFormat:@"%d", control.tag]

#2


3  

You don't use the name of an object in Interface Builder to refer to that object; it's just there for reference. (Interface Builder will also use it as a hint for what outlets connecting to the control and actions sent by the control might be named, but only as a hint.)

您不使用Interface Builder中的对象名称来引用该对象;它只是供参考。 (Interface Builder还将使用它作为连接到控件的出口和控件发送的操作可能被命名的提示,但仅作为提示。)

Instead, you add an outlet to a controller object that you connect to the object. This lets you access the object directly at runtime from your controller without going through any look-up step.

而是将插座添加到连接到对象的控制器对象。这使您可以在运行时直接从控制器访问对象,而无需执行任何查找步骤。

Also, it sounds like you have five buttons, with five things to do, all connected to the same action method. Don't do that.

此外,听起来你有五个按钮,有五个要做的事情,都连接到同一个动作方法。不要那样做。

In Cocoa and Cocoa Touch, you shouldn't typically create an action methods "per event" and then decide what to do based on which control sent the event. The controls in Cocoa handle events themselves, and translate them into higher-level actions. So you can implement five action methods in your controller, connect each button to its appropriate action method, and never have to decide what to do based on which control sent the action.

在Cocoa和Cocoa Touch中,您通常不应该“按事件”创建操作方法,然后根据发送事件的控件决定要执行的操作。 Cocoa中的控件自己处理事件,并将它们转换为更高级别的操作。因此,您可以在控制器中实现五个操作方法,将每个按钮连接到其相应的操作方法,而不必根据发送操作的控件来决定要执行的操作。

Obviously this isn't appropriate in all cases. For example, if you have a matrix of buttons with images that change at runtime, you would probably want them all to connect to the same action and distinguish them based on their tag property. A good rule of thumb is to use different action methods when dealing with "different" things, and use the same action method and control tags when dealing with "many of the same" thing.

显然这在所有情况下都不合适。例如,如果您有一个按钮矩阵,其中的图像在运行时会发生变化,您可能希望它们全部连接到同一个动作,并根据它们的标记属性区分它们。一个好的经验法则是在处理“不同”事物时使用不同的动作方法,并在处理“许多相同”事物时使用相同的动作方法和控制标记。

#3


3  

While I agree that tag will work in many circumstances, it's a pain to work with integer tags when you have a matrix of 100 buttons that are pushable where you want to identify: (1) what was pushed and (2) what value was pushed. I found myself starting to invent row/column naming schemes with tag numbers which got out of hand.

虽然我同意标签在许多情况下都能正常工作,但是如果你有一个100个按钮的矩阵可以在你想要识别的地方使用,那么使用整数标签是很痛苦的:(1)推送的内容和(2)推送的值是什么。我发现自己开始发明行/列命名方案,标签号已经失控。

I wanted multiple controls to share the same handler, and I wanted to carefully design my UI in IB to pass name/value pairs off to a key-value store based on what was pushed.

我希望多个控件共享同一个处理程序,我想在IB中仔细设计我的UI,根据推送的内容将名称/值对传递给键值存储。

As an alternative to tags, I came up with another workaround for UISegmentedControl (it works for other controls too).

作为标签的替代品,我想出了UISegmentedControl的另一种解决方法(它也适用于其他控件)。

(1) Create a new class and sub-class UISegmentedControl. Add a string property MyCustomKey to your new class.

(1)创建一个新的类和子类UISegmentedControl。将字符串属性MyCustomKey添加到新类。

@interface CustomSegmentedControl : UISegmentedControl
@property (nonatomic, retain) NSString* myCustomKey; 
@end

(2) Back in IB, modify your UISegmentedContol instances to be instances of CustomSegmentedControl. Used the IB "User Defined Runtime Attributes" to set the value of myCustomKey using IB. KeyValueCoding will take care of the setting of the properties for you:

(2)返回IB,将UISegmentedContol实例修改为CustomSegmentedControl的实例。使用IB“用户定义的运行时属性”使用IB设置myCustomKey的值。 KeyValueCoding将为您设置属性:

如何为控件指定名称并在事件方法中检索它?

(3) Wire up all your buttons to a single IBAction.

(3)将所有按钮连接到一个IBAction。

(4) In your IBAction, you can extract the key-value pairs now by reading back your custom attribute:

(4)在您的IBAction中,您现在可以通过回读自定义属性来提取键值对:

- (IBAction)myButtonPressed:(id) sender
{
    if ([sender isKindOfClass:[CustomSegmentedControl class]] == false)
        return;

    // get the key-values from the control
    CustomSegmentedControl *control = (CustomSegmentedControl *)sender;
    NSString *key = [control valueForKey:@"myCustomKey"];
    NSNumber *value = [NSNumber numberWithInteger:[control selectedSegmentIndex]];
    NSLog(@"Pressed control %@ with a value of %@", key, value);
}

In this case I was only interested in the integer value of a segmented control, but you could get any property off the control as the value.

在这种情况下,我只对分段控件的整数值感兴趣,但您可以将任何属性作为值从控件中获取。

Hope this helps.

希望这可以帮助。

#4


2  

The name field under Interface Builder Identity is something unique to Interface Builder; I'm actually not sure exactly how it's used, but it doesn't map to a usable property, ivar or method on your actual control. Instead, use the tag property (under the View attributes) to differentiate different controls from an action method if you don't otherwise keep a reference to them as an ivar. If I'm misunderstanding you and you want the button's title, just use currentTitle instead.

Interface Builder Identity下的名称字段是Interface Builder特有的;我实际上并不确定它是如何使用的,但它并没有映射到实际控制中的可用属性,ivar或方法。相反,如果不将其作为ivar引用,则使用tag属性(在View属性下)来区分不同的控件和action方法。如果我误解你并想要按钮的标题,只需使用currentTitle。

#5


0  

If the control has a name attribute, then:

如果控件具有name属性,则:

NSString *senderName = [sender name];

This isn't something most controls have. You might want:

这不是大多数控件所具有的。你可能想要:

NSString *senderName = [sender title];

If it was an NSButton, for instance. Or as Marc says, for a UIButton, use currentTitle.

例如,如果它是NSButton。或者正如Marc所说,对于UIButton,请使用currentTitle。

#6


0  

Try:

senderTitle = [sender currentTitle];