How to create local areas in Swift?

I regularly use local areas in Objective-C to make naming more understandable.

{ UILabel *label = [[UILabel alloc] init]; [self addSubview:label]; self.titleLabel = label; } 

I am trying to rewrite this code in Swift as follows:

 { let label = UILabel() self.addSubview(label) self.titleLabel = label } 

This gives me the following error:

Error: Braced block of statements is an unused closure.

So how can I create a local area in Swift?

+46
swift
Jun 03 '14 at 9:13
source share
5 answers

Update: In Swift 2.0, you simply use the do keyword:

 do { let label = UILabel() self.addSubview(label) self.titleLabel = label } 



This is true for Swift pre-2.0:

You can define something similar to this:

 func locally(@noescape work: () -> ()) { work() } 

And then use a locally block like this:

 locally { let g = 42 println(g) } 

(Inspired locally the Scala Predef object.)

+67
Jun 03 '14 at 10:14
source share

I do not think that's possible.

At least the grammar contained in the book, available on the iBooks store, does not mention this.

You can do it,

 if (true) { let a = 4 } 

but I think this is bad practice.

+6
Jun 03 '14 at 9:29
source share

As noted in the comments, anonymous nested areas in C are often a sign that you could write better code. For example, instead of simply doing work in a nested area that ultimately sets self.titleLabel , you could instead assign the result of evaluating the built-in closure:

 self.titleLabel = { let label = UILabel() label.text = "some text" // ... set other properties ... self.addSubview(label) return label }() 

This not only saves the label as a beautiful short name, which only refers to the piece of code that creates and sets it up, but it saves this piece of code associated with the property for which it creates the value. And it's more modular, because you could replace all closures with a call to some other shortcut function, if it ever became useful to adjust this code.

If you do this often, you can try creating a generic function that allows you to shorten your build code to this:

 self.titleLabel = makeSubview(UILabel()) { label in label.text = "some text" // other label properties } 

But I will leave the definition of such a function as an exercise for the reader .;)




As stated in Jean-Philippe Pellet's answer , in Swift 2.0, and later the do construct is an explicitly language-provided way to do this. (And the functional solution that he offers is a decent option for those who are still using Swift 1.x.)

Another Swift 1.x solution - without defining a new function - is to (explicitly) throw out the result of the closure immediately executed:

  _ = { print("foo") }() 
+2
Jan 27 '15 at 18:29
source share

In Swift 2, you can create a local scope with do -statement:

 do { let x = 7 print(x) } print(x) // error: use of unresolved identifier 'x' 

The main use case, however, is error handling using do-try-catch, as described in “Error Handling” in “Quick Language” , for example:

 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)") } 
+2
Jun 09 '15 at 17:00
source share

What I am doing is defining an anonymous function and executing it.

 // ... preceding code ... // ... might need semicolon here; { () -> () in // ... this is a local scope ... }() // ... following code ... 

You may need to put a semicolon at the end of the previous line so that Swift does not think it is a “closing close”. You can even place this semicolon on the same line immediately before opening the braces. So, implementing the OP source code:

 ;{ () -> () in let label = UILabel() self.addSubview(label) self.titleLabel = label }() 

EDIT Subsequently, I found that if true {...} returned instead. However, as Martin points out, in Swift 2 do {...} will be allowed as an official way to define an arbitrary scope. Thus, the solution to the problem will be nice.

-one
Jan 27 '15 at 18:31
source share



All Articles