Как и зачем использовать Labeled Statements в Swift?
Перед написанием данной статьи я спросил в нескольких iOS-чатах про эту фичу Swift, однако никто из iOS-разработчиков вообще(!) не знал о существовании Label Statements.
Зачем?
Некоторые сравнивают Label Statements с некоторой «огламуренной» разновидностью GOTO. Нагляднее всего это можно показать на двух вложенных Control Flow Statements, например на циклах:
let arrVeggies = ["eggplant", "cauliflower", "potato"] let arrColors = [0xffffff, 0x000000] vegLabel: for veg in arrVeggies { print(veg) for col in arrColors { if veg == "cauliflower" && col == 0x000000 { continue vegLabel } print(String(col, radix: 16)) } }
Перед первым циклом мы вставили
eggplant ffffff 0 cauliflower ffffff potato ffffff 0
На реальных проектах таким образом вы сможете оптимизировать производительность сложных вложенных циклов.
Давайте ещё рассмотрим пример с break
Работая в геймдеве, мне часто приходилось обходить 2-х мерные массивы, которые являются представлением 2D карты:
// ┌──▶ x // │ // ▼ // y let treasureIsland4x4 = [ ["empty", "empty", "empty", "empty"], ["empty", "empty", "empty", "empty"], ["empty", "empty", "empty", "empty"], ["treasure", "empty", "empty", "empty"] ] yScan: for (y, xRow) in treasureIsland4x4.enumerated() { // x Scan for (x, value) in xRow.enumerated() { if value == "treasure" { print("Found at x=\(x), y=\(y)") break yScan } } }
Результат будет:
Found at x=0, y=3
Массив мы предопределили литералами и «закопали» сокровище в начале последнего вложенного x массив. Если во вложенном цикле мы напишем break, то мы просто выйдем из x Scan цикла и нам придётся писать или условие со вторым break, или отдельную функцию с return.
Благодаря Label Statement мы сразу прерываем первый цикл. При написании оптимизированных алгоритмов вложенность бывает выше 2-х мерной и лейблы нам помогут сделать выполнение быстрее, а код короче.
Кроме циклов, лейблы можно ставить и на другие Control Flow Statements: На while-циклы:
whileLabel: while condition == true { … }
На repeat-while-циклы:
repeatLabel: repeat { … } while condition == true
На if-предписание:
ifLabel: if condition == true { … }
На switch-предписание:
switchLabel: switch condition { … }
Остались вопросы? Пишите их в комментариях!