太多样板代码的开关语句 - iOS

4

我有一个switch语句,会适当地向11个UILabel添加文本。然而,现在它变得有点冗长了,而且有太多相同的代码副本。我该如何进一步改进它呢?也许我可以创建一个标签数组,然后通过for循环来访问它们?

这里是switch语句的代码:

switch ([number_sorted count]) {

            case 1:
                label_1.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[0] integerValue]];
                break;

            case 2:
                label_1.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[0] integerValue]];
                label_2.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[1] integerValue]];
                break;

            case 3:
                label_1.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[0] integerValue]];
                label_2.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[1] integerValue]];
                label_3.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[2] integerValue]];
                break;

            case 4:
                label_1.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[0] integerValue]];
                label_2.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[1] integerValue]];
                label_3.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[2] integerValue]];
                label_4.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[3] integerValue]];
                break;

            case 5:
                label_1.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[0] integerValue]];
                label_2.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[1] integerValue]];
                label_3.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[2] integerValue]];
                label_4.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[3] integerValue]];
                label_5.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[4] integerValue]];
                break;

            case 6:
                label_1.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[0] integerValue]];
                label_2.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[1] integerValue]];
                label_3.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[2] integerValue]];
                label_4.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[3] integerValue]];
                label_5.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[4] integerValue]];
                label_6.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[5] integerValue]];
                break;

            case 7:
                label_1.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[0] integerValue]];
                label_2.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[1] integerValue]];
                label_3.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[2] integerValue]];
                label_4.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[3] integerValue]];
                label_5.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[4] integerValue]];
                label_6.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[5] integerValue]];
                label_7.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[6] integerValue]];
                break;

            case 8:
                label_1.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[0] integerValue]];
                label_2.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[1] integerValue]];
                label_3.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[2] integerValue]];
                label_4.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[3] integerValue]];
                label_5.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[4] integerValue]];
                label_6.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[5] integerValue]];
                label_7.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[6] integerValue]];
                label_8.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[7] integerValue]];
                break;

            case 9:
                label_1.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[0] integerValue]];
                label_2.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[1] integerValue]];
                label_3.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[2] integerValue]];
                label_4.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[3] integerValue]];
                label_5.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[4] integerValue]];
                label_6.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[5] integerValue]];
                label_7.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[6] integerValue]];
                label_8.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[7] integerValue]];
                label_9.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[8] integerValue]];
                break;

            case 10:
                label_1.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[0] integerValue]];
                label_2.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[1] integerValue]];
                label_3.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[2] integerValue]];
                label_4.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[3] integerValue]];
                label_5.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[4] integerValue]];
                label_6.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[5] integerValue]];
                label_7.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[6] integerValue]];
                label_8.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[7] integerValue]];
                label_9.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[8] integerValue]];
                label_10.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[9] integerValue]];
                break;

            case 11:
                label_1.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[0] integerValue]];
                label_2.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[1] integerValue]];
                label_3.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[2] integerValue]];
                label_4.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[3] integerValue]];
                label_5.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[4] integerValue]];
                label_6.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[5] integerValue]];
                label_7.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[6] integerValue]];
                label_8.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[7] integerValue]];
                label_9.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[8] integerValue]];
                label_10.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[9] integerValue]];
                label_11.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[10] integerValue]];
                break;

            default:
                break;
        }

感谢您抽出时间,丹。

不要使用11个ivars来存储标签,而是使用一个标签数组。这样代码就可以变成一个简单的循环。 - rmaddy
另一个解决方案是使用 objc_... 运行时函数动态查找标签,例如创建标签的选择器名称,然后调用 objc_msgSend()。这样就无需更改它们的声明。 - Thomas Tempelmann
3个回答

4
另一个选项是使用 switch 语句的 "fall through" 属性。
switch ([number_sorted count]) {
    case 11:
        label_11.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[10] integerValue]];
    case 10:
        label_10.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[9] integerValue]];
    case 9:
        label_9.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[8] integerValue]];
    case 8:
        label_8.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[7] integerValue]];
    case 7:
        label_7.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[6] integerValue]];
    case 6:
        label_6.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[5] integerValue]];
    case 5:
        label_5.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[4] integerValue]];
    case 4:
        label_4.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[3] integerValue]];
    case 3:
        label_3.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[2] integerValue]];
    case 2:
        label_2.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[1] integerValue]];
    case 1:
        label_1.text = [NSString stringWithFormat:@"%ld", (long)[number_sorted[0] integerValue]];
    default:
        break;
}

这个方法安全吗?因为(显而易见的原因)你已经省略了break语句。希望这不会导致任何意外的异常? - Supertecnoboff
2
这个答案中的代码是安全的。通常情况下,如果缺少 break,那么这是一个错误,但在这种情况下,这正是你想要的。作为一种惯例,我总是在缺少 break 的位置添加注释,澄清它真的不应该存在。 - rmaddy
4
我还要补充一点,虽然这个答案看起来很好,但它仍然是错误的解决方案。它很脆弱,容易出现由于简单的拼写错误而导致的漏洞。它也不具备良好的可扩展性。你真的应该使用“循环”解决方案。它更少有漏洞,更具可扩展性,而且阅读和编写起来都更容易。 - rmaddy
我真的很不喜欢它。它仍然没有任何理由地重复了很多代码。这个概念很好,但在这种情况下,我会说它不合适。 - Daij-Djan
不幸的是,我必须同意DD和M的观点。这太糟糕了。编程的整个基本性质就是通过使用更高级别的概念来消除重复。虽然超级管理员能够理解在这种特定的编程语言中可以通过switch体进行跌落,但这是唯一的教育品质。这是OP提高集合、在代码中制作控件或其他方面的绝佳机会。(而且仍然没有人关心空白项!呵呵) - Fattie
显示剩余4条评论

2

使用两个数组:1. 包含所有标签,2. 包含各标签数量。
你已经有了第2部分,所以:

首先,在你的类中添加一个NSArray *_labels
然后在viewDidLoad中执行_labels = @[label1, label2, label3];

然后针对开关操作进行处理。

for(int i = 0; i < number_sorted.count; i++) {
    ((UILabel*)_labels[i]).text = [NSString stringWithFormat:@"%ld", [number_sorted[i] integerValue]];
}

我收到了一个错误,类型为 id 的对象中未找到属性“text”。 - Supertecnoboff
1
@Daij-Djan,我在SO上看到很多变量和实例变量都有一个前导下划线“_”。我知道属性会生成带有前导下划线的实例变量,但为什么要以这种方式访问它们呢?通常,如果有属性,应该通过getter/setter(如self.labels)来访问值。是否存在不使用属性的偏见?是否有一些指导者/班级或教程推荐这样做? - zaph
哦,我的错 @Supertecnoboff,请不要使用“.”语法或强制转换。我“修复”了代码。 - Daij-Djan
直接变量(direct vars)非常方便 :D - Daij-Djan
你甚至可以将它们放在.m文件中..在实现部分,即--> @implementation MyClass { id _myVar; } ... @end - Daij-Djan
显示剩余3条评论

2
只需将您的UILabel放入NSArray中,然后可以对该数组进行迭代。在Interface Builder中,您可以将一堆元素添加到IBOutletCollection中,这非常方便(只需将多个元素拖在一起,就像创建一个IBOutlet一样,它会提供创建IBOutletCollection的选项)。
请注意,IBOutletCollection不保证顺序。因此,您可能需要在IB中添加标记来跟踪它们。我经常在viewDidLoad中按标记对我的集合进行排序。
如果您以编程方式构建此系统,则可以直接将它们放入数组中。
有时候,跟踪标记仍然很麻烦,所以我会稍微作弊。我只使用subviews遍历所有视图并查找我的标签。然后,我按y-origin对它们进行排序并将它们放入数组中。当然,这有点脆弱,并且需要大量关于您的视图的特殊知识,但是视图控制器预计具有该知识。我偶尔使用这种技术创建混合的IB /编程界面,这样我就可以在IB中布置所有内容,但是在代码中连接所有内容(操作、字体选择等)。当存在许多几乎相同的UI元素时,我尤其这样做。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接