Как создать локальные области в Swift?
Я регулярно использую локальные области в Objective-C, чтобы сделать именование более понятным.
{
UILabel *label = [[UILabel alloc] init];
[self addSubview:label];
self.titleLabel = label;
}
Я пытаюсь переписать этот код в Swift следующим образом:
{
let label = UILabel()
self.addSubview(label)
self.titleLabel = label
}
Это дает мне следующую ошибку:
Error: Braced block of statements is an unused closure.
Итак, как я могу создать локальную область в Swift?
Ответы
Ответ 1
Обновление: В Swift 2.0 вы просто используете ключевое слово do
:
do {
let label = UILabel()
self.addSubview(label)
self.titleLabel = label
}
Это верно для Swift pre-2.0:
Вы можете определить что-то похожее на это:
func locally(@noescape work: () -> ()) {
work()
}
И затем используйте такой блок locally
следующим образом:
locally {
let g = 42
println(g)
}
(Вдохновленный locally
в Scala Predef объект.)
Ответ 2
Я не думаю, что это возможно.
По крайней мере, грамматика, содержащаяся в книге, доступной в магазине iBooks, не упоминает об этом.
Вы можете сделать это,
if (true) {
let a = 4
}
но я думаю, что это плохая практика.
Ответ 3
Как отмечено в комментариях, анонимные вложенные области на C часто являются признаком того, что вы могли бы писать лучший код. Например, вместо простого выполнения работы во вложенной области, которая в конечном итоге устанавливает self.titleLabel
, вы можете
вы могли бы вместо этого присвоить результат оценки встроенного закрытия:
self.titleLabel = {
let label = UILabel()
label.text = "some text"
// ... set other properties ...
self.addSubview(label)
return label
}()
Это не только сохраняет label
как красивое короткое имя, которое относится только к фрагменту кода, который создает и настраивает его, но сохраняет этот кусок кода, связанный с свойством, для которого он создает значение. И он более модульный, поскольку вы могли бы заменить все закрытие вызовом какой-либо другой функции создания ярлыков, если бы когда-нибудь стало полезно откорректировать этот код.
Если вы часто это делаете, вы можете попробовать создать общую функцию, которая позволит вам сократить свой код построения до этого:
self.titleLabel = makeSubview(UILabel()) { label in
label.text = "some text"
// other label properties
}
Но я оставлю определение такой функции, как упражнение для читателя.;)
Как указано в ответ Jean-Philippe Pellet, в Swift 2.0, а позже конструкция do
- это явно предоставленный языком способ сделать это. (И функциональное решение, которое он предлагает, является достойным вариантом для тех, кто все еще использует Swift 1.x.)
Другое решение Swift 1.x - без определения новой функции - заключается в (явно) выкидывать результат немедленно выполненного закрытия:
_ = {
print("foo")
}()
Ответ 4
В Swift 2 вы можете создать локальную область с do
-statement:
do {
let x = 7
print(x)
}
print(x) // error: use of unresolved identifier 'x'
Основным вариантом использования, однако, является обработка ошибок с помощью do-try-catch,
как описано в "Обработка ошибок"
в "Язык быстрого языка" , например:
do {
let jsonObj = try NSJSONSerialization.JSONObjectWithData(jsonData, options: [])
// success, do something with `jsonObj`...
} catch let error as NSError {
// failure
print("Invalid JSON data: \(error.localizedDescription)")
}
Ответ 5
Что я делаю, это определить анонимную функцию и выполнить ее.
// ... preceding code ...
// ... might need semicolon here;
{
() -> () in
// ... this is a local scope ...
}()
// ... following code ...
Возможно, вам придется положить точку с запятой в конце предыдущей строки, чтобы Swift не думал, что это "закрывающее закрытие". Вы можете даже разместить эту точку с запятой в одной строке непосредственно перед открытием фигурной скобки. Итак, реализуя исходный код OP:
;{
() -> () in
let label = UILabel()
self.addSubview(label)
self.titleLabel = label
}()
EDIT Впоследствии я обнаружил, что вместо этого возвращаюсь if true {...}
. Однако, как указывает Мартин, в Swift 2 do {...}
будет разрешен как официальный способ определения произвольной области видимости. Таким образом, решение проблемы будет приятно.