如何从 Objective-C 代码中删除一次性使用的类变量?

发布于 2024-08-19 03:11:46 字数 1044 浏览 6 评论 0原文

我正在编写一些 Objective-C 代码,并且经常遇到必须使用类变量来存储一次性使用的值的情况。吃完之后我就不再需要它了。对我来说,将此值存储在类变量中似乎有点代码味道。实际上,该值应该作为参数传递给我正在使用的方法。

我在消费委托时通常会遇到这种情况。例如,我有一个带有多个按钮的 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;
}

正如您在此处看到的,actionSheet clickedButtonAtIndex 回调不允许我传递 activeField,因此我必须使用类变量。这样写似乎更正确:

- (void)actionSheet:(UIActionSheet *)actionSheet parameterValue:(id)parameter {
    parameter.text = value_from_UIActionSheet;
}

我相信(?)我可以子类化 UIActionSheet 和 UIActionSheet 委托并添加我需要的签名,但这似乎比其价值更多的努力。

所以我的问题是做我想做的事情的最佳方法是什么?

我不一定想更改我创建的日期选择器/操作表界面(尽管如果有在 UIView 上设置多个日期同时保持 DatePicker 不受影响的更好模式,我洗耳恭听。)

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.

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.

- (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:

- (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.

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.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

も让我眼熟你 2024-08-26 03:11:46

在这种情况下,我认为 UIActionSheet 的简单子类将是可行的方法:

@interface SpecialActionSheet : UIActionSheet
{
    id parameter;
}
@property (assign) id parameter;
@end

@implementation SpecialActionSheet
@synthesize parameter;
@end

这应该足够了,因为您要做的就是让 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;
}

In this case, I think a simple subclass of UIActionSheet would be the way to go:

@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:

- (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;
}
风吹短裙飘 2024-08-26 03:11:46

在这些情况下,我通常的方法是使用 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];
}

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:

...
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];
}
薄荷梦 2024-08-26 03:11:46

另一个解决方案是使用关联存储。

UIActionSheet 可能已经有了它。您可以通过

[myActionSheet setValue:@"test value" forKey:@"testKey];
NSLog(@"%@",[myActionSheet valueForKey:@"testKey];

关联存储来测试它,如果没有过度使用的话,它是相当不错的。

Another solution is to use associative storage.

UIActionSheet might already have it. You can test it by

[myActionSheet setValue:@"test value" forKey:@"testKey];
NSLog(@"%@",[myActionSheet valueForKey:@"testKey];

Associative storage is rather nifty if not overused.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文