I'm writing some Objective-C code and I've frequently hit the situation where I have to use a class variable to store a value for one time use. After consuming it I no longer need it. To me, storing this value in a class variable seems like code smell. Really the value should be passed in as a parameter to the methods I'm using.
我正在编写一些Objective-C代码,而且我经常遇到必须使用类变量来存储一次使用值的情况。食用后我不再需要它了。对我来说,将这个值存储在类变量中似乎是代码味道。确实应该将值作为参数传递给我正在使用的方法。
I run across this usually when I'm consuming delegates. As an example, I have a UI with multiple buttons used to load and display a UIActionSheet
when they're tapped. This action sheet contains a date picker which sets a value for a UILabel
when the action sheet is dismissed.
当我消耗代表时,我经常遇到这种情况。作为一个例子,我有一个带有多个按钮的UI,用于在点击时加载和显示UIActionSheet。此操作表包含日期选择器,可在操作表解除时为UILabel设置值。
- (IBAction)setPurchaseDateTapped {
self.activeField = purchaseDate;
[self loadDatePickerActionSheet:@"Edit Purchase Date"];
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
self.activeField.text = value_from_UIActionSheet;
}
As you can see here, the actionSheet clickedButtonAtIndex callback doesn't allow me to pass the activeField
so I have to use a class variable. It seems more correct to write this:
正如你在这里看到的,actionSheet clickedButtonAtIndex回调不允许我传递activeField所以我必须使用类变量。写这个似乎更正确:
- (void)actionSheet:(UIActionSheet *)actionSheet parameterValue:(id)parameter {
parameter.text = value_from_UIActionSheet;
}
I believe(?) that I can subclass the UIActionSheet and UIActionSheet delegate and add the signatures that I require, but again this seems like more effort than it's worth.
我相信(?)我可以继承UIActionSheet和UIActionSheet委托并添加我需要的签名,但是这似乎更值得付出努力。
So my question is what is the best way to do what I'm trying to do?
所以我的问题是,做我想做的事情的最佳方法是什么?
I don't necessarily want to change the date picker/action sheet interface that I've created (although if there's a better pattern for setting multiple dates on a UIView while keeping the DatePicker out of the way, I'm all ears.)
我不一定想要更改我创建的日期选择器/操作表界面(尽管如果有一个更好的模式可以在UIView上设置多个日期同时保持DatePicker不碍事,我会全力以赴。)
3 个解决方案
#1
3
In this case, I think a simple subclass of UIActionSheet
would be the way to go:
在这种情况下,我认为UIActionSheet的一个简单子类将是要走的路:
@interface SpecialActionSheet : UIActionSheet
{
id parameter;
}
@property (assign) id parameter;
@end
@implementation SpecialActionSheet
@synthesize parameter;
@end
That should be enough, since all you want to do is have the actionSheet keep a parameter. Now, your code might look as follows:
这应该足够了,因为你想要做的就是让actionSheet保留一个参数。现在,您的代码可能如下所示:
- (void)loadDatePickerActionSheet:(NSString *)caption forField:(UITextField *)field {
//...
datePickerActionSheet.parameter = field;
}
- (IBAction)setPurchaseDateTapped {
[self loadDatePickerActionSheet:@"Edit Purchase Date" forField:purchaseDate];
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
UITextField * field = ((SpecialActionSheet *)actionSheet).parameter;
field.text = value_from_UIActionSheet;
}
#2
2
My usual approach in these situations is to use the tag property on UIAlertViews, and do a switch on it (it's an integer). It's not quite as nice as having a string or something to pass down, but if you've got multiple alerts, it's an easy way to disambiguate. For example:
在这些情况下我通常的做法是在UIAlertViews上使用tag属性,然后对它进行切换(它是一个整数)。它不像让字符串或其他东西传递下来那么好,但如果你有多个警报,这是一种消除歧义的简单方法。例如:
...
actionSheet.tag = [fields indexOfObject: self.activeField];
... //fields is an NSArray of all the field objects I might have on the screen
- (void)actionSheet:(UIActionSheet *)actionSheet parameterValue:(id)parameter {
[[field objectAtIndex: actionSheet.tag] setText: value_from_UIActionSheet];
}
#3
2
Another solution is to use associative storage.
另一种解决方案是使用关联存储。
UIActionSheet might already have it. You can test it by
UIActionSheet可能已经拥有它。你可以测试一下
[myActionSheet setValue:@"test value" forKey:@"testKey];
NSLog(@"%@",[myActionSheet valueForKey:@"testKey];
Associative storage is rather nifty if not overused.
如果不过度使用,关联存储相当漂亮。
#1
3
In this case, I think a simple subclass of UIActionSheet
would be the way to go:
在这种情况下,我认为UIActionSheet的一个简单子类将是要走的路:
@interface SpecialActionSheet : UIActionSheet
{
id parameter;
}
@property (assign) id parameter;
@end
@implementation SpecialActionSheet
@synthesize parameter;
@end
That should be enough, since all you want to do is have the actionSheet keep a parameter. Now, your code might look as follows:
这应该足够了,因为你想要做的就是让actionSheet保留一个参数。现在,您的代码可能如下所示:
- (void)loadDatePickerActionSheet:(NSString *)caption forField:(UITextField *)field {
//...
datePickerActionSheet.parameter = field;
}
- (IBAction)setPurchaseDateTapped {
[self loadDatePickerActionSheet:@"Edit Purchase Date" forField:purchaseDate];
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
UITextField * field = ((SpecialActionSheet *)actionSheet).parameter;
field.text = value_from_UIActionSheet;
}
#2
2
My usual approach in these situations is to use the tag property on UIAlertViews, and do a switch on it (it's an integer). It's not quite as nice as having a string or something to pass down, but if you've got multiple alerts, it's an easy way to disambiguate. For example:
在这些情况下我通常的做法是在UIAlertViews上使用tag属性,然后对它进行切换(它是一个整数)。它不像让字符串或其他东西传递下来那么好,但如果你有多个警报,这是一种消除歧义的简单方法。例如:
...
actionSheet.tag = [fields indexOfObject: self.activeField];
... //fields is an NSArray of all the field objects I might have on the screen
- (void)actionSheet:(UIActionSheet *)actionSheet parameterValue:(id)parameter {
[[field objectAtIndex: actionSheet.tag] setText: value_from_UIActionSheet];
}
#3
2
Another solution is to use associative storage.
另一种解决方案是使用关联存储。
UIActionSheet might already have it. You can test it by
UIActionSheet可能已经拥有它。你可以测试一下
[myActionSheet setValue:@"test value" forKey:@"testKey];
NSLog(@"%@",[myActionSheet valueForKey:@"testKey];
Associative storage is rather nifty if not overused.
如果不过度使用,关联存储相当漂亮。