将 UIActionSheet 选项连接到操作的正确方法
在 iPhone 应用程序中使用 UIActionSheet 时,将操作与按钮匹配的典型方法似乎非常脆弱且美观不愉快。也许是因为我的 C/C++ 背景(更多 Perl、Java、Lisp 等)。按钮索引的匹配看起来像是太多的神奇数字,而且太脱节,无法避免简单的逻辑或一致性错误。
例如,
UIActionSheet *sources = [[UIActionSheet alloc]
initWithTitle:@"Social Networks"
delegate:self
cancelButtonTitle:@"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:@"Twitter", @"Facebook", @"Myspace", @"LinkedIn", @"BlahBlah", nil
];
<snip>
-(void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex {
if (buttonIndex == [actionSheet cancelButtonIndex]) {
// all done
} else if (buttonIndex == 0) {
// Twitter
} else if (buttonIndex == 1) {
// Facebook
} else if (buttonIndex == 2) {
// LinkedIn
} else if (buttonIndex == 3) {
// Myspace
}
}
请注意,操作处理代码中至少有两个错误(至少根据注释)。
我缺少的是避免 Objective-C 中这种脱节的正确设计模式。如果这是 Perl,我将首先构建一个按钮选项数组,然后可能创建一个快速查找表哈希,该哈希将对应于为每个项目执行适当操作的另一个对象或子例程查找表。在java中,原始列表可能首先是带有回调的对象。我知道我可以构建一个字典来模仿 perl 哈希,但这对于 3-4 个选项来说感觉非常笨拙和麻烦。我还考虑过使用枚举来掩盖索引的魔力,但这只是问题的一小部分。
真正的问题似乎是没有(简单?)方法可以在一个地方指定按钮字符串列表和相应的操作,从而消除在添加/删除/重新排序选项时在两个地方修改代码的需要,从而使其有效不可能犯我的示例代码所犯的那种错误。
我并不是想发起一场编程语言圣战,我只是想弄清楚在这种情况下(我相信 Objective C 中的许多其他模式)将按钮字符串列表连接到操作列表的正确设计模式是什么。
While using a UIActionSheet in an iphone app, the typical methods of matching actions to buttons seem very fragile and aesthetically unpleasant. Perhaps its due to my minimal C/C++ background (more Perl, Java, Lisp and others). Matching on button indexes just seems like too many magic numbers and too disconnected to avoid simple logical or consistency errors.
For instance,
UIActionSheet *sources = [[UIActionSheet alloc]
initWithTitle:@"Social Networks"
delegate:self
cancelButtonTitle:@"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:@"Twitter", @"Facebook", @"Myspace", @"LinkedIn", @"BlahBlah", nil
];
<snip>
-(void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex {
if (buttonIndex == [actionSheet cancelButtonIndex]) {
// all done
} else if (buttonIndex == 0) {
// Twitter
} else if (buttonIndex == 1) {
// Facebook
} else if (buttonIndex == 2) {
// LinkedIn
} else if (buttonIndex == 3) {
// Myspace
}
}
Notice there's at least two errors in the action handling code (according to the comments at least).
What I'm missing is the correct design pattern for avoiding that disconnect in Objective-C. If this were perl, I would first build an array of my button options and then probably create a quick lookup table hash that would correspond to another lookup table of objects or subroutines that did the appropriate thing for each item. In java, the original list would probably be objects in the first place with callbacks. I know I could build a Dictionary to mimic the perl hash but that feels very unwieldy and cumbersome for 3-4 options. I've also considered using a enum to mask the magic-ness of indexes but that's only a minor part of the problem.
The real problem seems to be that there's no (simple?) way to specify BOTH the list of button strings and corresponding actions in one place thereby eliminating the need to modify code in two places when adding/removing/reordering options and thus making it effectively impossible to make the kinds of mistakes that my sample code makes.
I'm not trying to start a programming language holy war, I just want to figure what the correct design pattern in this scenario (and I believe many others in Objective C) for connecting the list of button strings to the list of actions.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我更喜欢这种方式
I prefer this way
我完全同意这个问题。 Apple 的设计鼓励使用幻数,当我看到所有建议对按钮索引使用硬编码数字的解决方案时,我感到有点震惊。
这是我的 Swift 解决方案。
使用每个按钮标题的本地化字符串填充字典,其中键是枚举中的项目:
创建操作表,通过枚举值从字典中获取按钮标题:
最后,在 clickedButtonAtIndex 代码中,根据字典中的本地化字符串检查单击按钮的标题:
I completely agree with the question. Apple's design here encourages the use of magic numbers, and I was a little shocked to see all the solutions out there recommending use of hardcoded numbers for the button indexes.
Here's my solution for Swift.
Populate a dictionary with the LOCALIZED strings for each button title, where the keys are items from the enum:
Create the action sheet, getting the button titles from the dictionary by their enum value:
Finally, in the clickedButtonAtIndex code, check the title of the clicked button against the localized strings in the dictionary:
也许您可以将按钮的操作放入数组中,
然后在 didDismissWthButtonIndex 中,
我非常确定您可以将更复杂的对象放入数组中,包括按钮信息和方法,然后将其全部包含在数组中。可能对数组的索引进行更好的错误检查......等等
说实话,在我读到这个问题之前,我从来没有想过这个模式,所以这只是我的想法
Maybe you could put the actions for the buttons in an array
then in didDismissWthButtonIndex
I am pretty certain you could put a more complex object in the array including button info and method and then have it all contained in the array. Probably better error checking on the index of the array....etc
To be honest with you I never thought about this pattern much until i read the question so this is just off the top of my head
那个怎么样?
这样,您就不必担心索引,因为按钮和操作都添加在同一位置。
How about that one?
In that way, you don't have to worry about indexes since buttons and actions are added in the same place.
基于亚伦的选择器建议,我真的很喜欢现在做一个简单的临时调度方法的想法。它成功地避免了处理错误选项的可能性,并提供了清晰的关注点分解。当然,我可以想象一个用例,您希望首先为每个选项执行其他操作,例如实例化一个对象并向其传递选项字符串,就像 Toro 的答案一样。
这是一个调用“actionTwitter”等方法的简单调度:
Building on Aaron's selector suggestion, I really like the idea now of doing a simple ad-hoc dispatch method. It successfully avoids the possibility of handling the wrong option as well as providing a clean factorization of concerns. Of course, I could imagine a use case where you want to do something else first for each option, such as instantiating an object and passing it the option string much like Toro's answer.
Here's a simple dispatch that calls methods such as 'actionTwitter':