Can you continue a loop if optional downcasting fails in Swift? - swift

It's a very common idiom to continue a loop if some condition fails on an element.
Say we want to do something to all subviews of a certain type (and, for some reason, don't want to duck type things). Ideally, we would write:
for view in self.subviews as [NSView] { // cast required in beta 6
if (let specificView = view as? SpecificView) == nil { // <- Error here
continue
}
// Do things at a sensible indentation level
}
The above code fails with 'Pattern variable binding cannot appear in an expression', as in this question.
However, this seems like such a common pattern that there has to be a way to do it in Swift. Am I missing something?
EDIT: Now that I think about it, this appears to fall afoul of the scoping rules for if let statements, which only scope the variable to the inner block.
With that in mind, I'd like to broaden the question a little: how do people apply this pattern generally in Swift?

This is a somewhat common pattern, but it is not a good pattern. I've seen it inject bugs into ObjC projects. It assumes too much about the view hierarchy, and winds up being fragile when that changes (such as when someone injects an extra view you weren't expecting in order to manage rotations; true story). The better pattern is to maintain a property that points to your SpecificView (or views) that you want to track. Downcasting in general is something to be avoided, not optimized.
That said, it is not a terrible pattern, and sometimes it is a very useful pattern. So how might you handle it?
let specifics = self.subviews
.filter { $0 is SpecificView }
.map { $0 as SpecificView }
for view in specifics { ... }
That's kind of a common pattern, so maybe we can genericize it?
extension Array {
func filterByClass<T>(c: T.Type) -> [T] {
return self.filter { $0 is T }.map { $0 as T }
}
}
for view in self.subviews.filterByClass(SpecificView) { ... }
That said, I think this approach should be avoided wherever possible rather than excessively simplified.

Related

Swift short syntax of execution

I am looking for the way to write short syntax.
For instance. In JS, PHP and etc.
var a = 1 ;
function Foo ()-> void {}
a && Foo() ;
if a exists, run Foo.
a and Foo itself already mean exist or not, the syntax is away better looks....
However, in Swift, the typing checking is kinda of tough.
var a = 1 ;
func Foo ()-> Foid {} ;
a && Foo();
will generate neither are Bool returning error.
a != nil && Foo() ;
this can resolve and variable condition, but what if the better bypass for the function condition? I just dont want to write something like
if( a != nil ) { Foo() } ;
Yet what is the better syntax for Not Exist?
if ( !a ) or !a //is easy and better looks...
I found not similar thing in swift...
if( a == nil ) // will throws error when its not Optional Typing.
guard var b = xxx else {} // simply for Exist and very long syntax.
Thank you for your advice!
As mentioned by other contributors, Swift emphasizes readability and thus, explicit syntax. It would be sacrilege for the Swift standard library to support Python-style truth value testing.
That being said, Swift’s extensibility allows us to implement such functionality ourselves—if we really want to.
prefix func !<T>(value: T) -> Bool {
switch T.self {
case is Bool.Type:
return value as! Bool
default:
guard Double(String(describing: value)) != 0
else { return false }
return true
}
}
prefix func !<T>(value: T?) -> Bool {
guard let unwrappedValue = value
else { return false }
return !unwrappedValue
}
var a = 1
func foo() -> Void { }
!a && !foo()
Or even define our own custom operator:
prefix operator ✋
prefix func ✋<T>(value: T) -> Bool {
/// Same body as the previous example.
}
prefix func ✋<T>(value: T?) -> Bool {
guard let unwrappedValue = value
else { return false }
return ✋unwrappedValue
}
var a = 1
func foo() -> Void { }
✋a && ✋foo()
The expectations you've developed from dynamic languages like PHP and JS (and Ruby, Python for that matter) are almost universally inapplicable to static languages like Swift.
Swift is a statically compiled language. If you reference a variable that doesn't exist, it's not legal Swift code, and the compiler will fail your build. Given that, the question of "how do I check if a variable is undefined?" is completely moot in Swift. If you have a successfully compiling program that references a variable a, then a exists. There's absolutely no reason for a check, and so a mechanism for it doesn't even exist.
Static vs Dynamic typing
Static type systems are like mathematical proof systems. They produce rigerous proofs that certain aspects of your program are valid. This has trade-offs. The rigidity buys you many guarantees. For example, you'll never have a valid Swift program where you accidentally pass an Int where a Bool is expected. The static type system makes that class of error literally impossible, so it's not something you have to remember to check for yourself.
On the other hand, many truths are easier to intuit than to prove. Thus, there's great utility in scripting and dynamic languages, because they don't demand the rigorous proofs of your claims that static languages require. On the down side, their type systems "do" much less. For example, JS happily lets you reference an undefined variable. To remedy this, JS provides a way for you to do a run-time check to see whether a variable is defined or not. But this isn't a problem Swift has, so the "solution" is absent.
When static typing is too hard
Swift actually takes a middle ground position. If you find yourself with a statement that's obviously true, but hard to prove to the compiler, various "escape hatches" exist that allow you to leave the safety of the type system, and go into dynamic land. For example, if you look at an IBOutlet, and see that it's connected to an element in a storyboard, you can intuitively be sure that the IBOutlet is not nil. But that's not something you can prove to the compiler, and hence when you see implicitly unwrapped optionals being used for IBOutlets.
Implicitly unwrapped optionals are one such "escape hatch". The Any type is another, as is unsafeBitcast(_:to:), withoutActuallyEscaping(_:), as!, try!, etc.
Swift takes type safety very seriously. Unlike C or JS we can not use anything that doesn't resolve to Bool value type in If statement in Swift. So there won't be a short hand for that(at-least that I know of). Regarding below code
if( a == nil ) // will throws error when its not Optional Typing.
Swift doesn't allow you to set nil to non optional types. So there is no need to check for nil. By the way both Obj-C and Swift use verbose syntax, we need to get use to that.
In this case you are trying to force Swift to work in a way that you are used to with other languages like JavaScript or PHP, as you say in your comment. There are a few reasons why your code won't compile, but it mainly falls on the fact that Swift doesn't do the same truthy and falsy stuff JS does.
var a = 1
if a {
print("won't compile")
}
//'Int' is not convertible to 'Bool'
In Swift it's better to use an actual Bool value if that's what it's supposed to be, or if it's truly supposed to be an Int you're just going to have to check the value
var a = true
if a {
print("this compiles")
}
or
var a = 1
if a > 0 {
print("this compiles too")
}
Swift really isn't meant to be as loose as JS, so you should just embrace that and take advantage of the safety and readability.
Here is one way most similar to what you designed.
You may have to set the type of a to Int?:
var a: Int? = 1
func foo ()-> Void {}
a.map{_ in foo()}

compactMap on sequence() not lazy?

Every once in a while I have to walk up the responder chain to reach an instance of a known class. (Just accept this for purposes of the question.) I've been doing this with a while loop, but it occurred to me that it would be cooler to use sequence(), which can express the responder chain itself neatly like this:
let chain = sequence(first: someView as UIResponder) {$0.next}
That's brilliant because so far we haven't actually done any walking; the sequence is lazy and the anonymous function won't be executed until we start asking for elements. To prove that, let me instrument that code with a print statement:
let chain = sequence(first: someView as UIResponder) {r in print(r); return r.next}
Okay, so let's say I'm looking for the first ViewController instance in the chain. I can find it like this:
if let vc = (chain.first {$0 is ViewController}) as? ViewController {
print(vc)
}
The printout shows that laziness is maintained: we walked up the responder chain until we got to the ViewController and stopped. Perfect! Inside the curly braces, vc is typed as ViewController and we're off to the races.
It will not have escaped your attention, however, that that's ugly. I'm both testing and casting. Is there a way I can just cast without testing and still end up with a ViewController?
This is elegant and it works fine:
for case let vc as ViewController in chain {
print(vc)
break
}
That's lovely and laziness is maintained — but I have to remember to say break at the end, which sort of ruins everything.
Okay, so I was really hopeful when I thought of this:
if let vc = (chain.compactMap{ $0 as? ViewController }.first) {
print(vc)
}
It works in the sense that it compiles and gets the right answer and looks nice, but I've lost laziness. The entire chain is being traversed. Does compactMap lose laziness? Is there a way to get it back? (Or is there some other elegant way that has completely escaped me?)
The issue is not compactMap, per se. There are two issues:
If you want the sequence to call compactMap lazily, you need to use lazy.
It would appear that first is preventing the lazy behavior. If you use first(where:), though, you do enjoy the lazy behavior.
Thus, while somewhat inelegant, the following achieves what you’re looking for:
if let vc = (chain.lazy.compactMap { $0 as? ViewController }.first { _ in true } ) {
...
}
Or, as you say, you can implement first (or lazyFirst) on Sequence:
extension Sequence {
var first: Element? {
return first { _ in true }
}
}
And then this more simplified rendition now is still lazy:
if let vc = chain.lazy.compactMap({ $0 as? ViewController }).first {
...
}

When to use forEach(_:) instead of for in?

As documented in both Array and Dictionary forEach(_:) Instance methods:
Calls the given closure on each element in the sequence in the same
order as a for-in loop.
Nevertheless, adapted from Sequence Overview:
A sequence is a list of values that you can step through one at a
time. The most common way to iterate over the elements of a sequence
is to use a for-in loop.
Implying that iterating sequence by forEach(_:) or for in:
let closedRange = 1...3
for element in closedRange { print(element) } // 1 2 3
closedRange.forEach { print($0) } // 1 2 3
Or (Array):
let array = [1, 2, 3]
for element in array { print(element) } // 1 2 3
array.forEach { print($0) } // 1 2 3
Would gives the same output.
Why forEach(_:) even exist? i.e what is the benefit of using it instead of the for in loop? would they be the same from performance point view?
As an assumption, it could be a syntactic sugar especially when working with functional programming.
There is no performance benefit offered by forEach. In fact, if you look at the source code, the forEach function actually simply performing for-in. For release builds, the performance overhead of this function over simply using for-in yourself is immaterial, though for debug builds, it results in an observable performance impact.
The main advantage of forEach is realized when you are doing functional programming, you can add it to a chain of functional calls, without having to save the prior result into a separate variable that you'd need if you used for-in syntax. So, instead of:
let objects = array.map { ... }
.filter { ... }
for object in objects {
...
}
You can instead stay within functional programming patterns:
array.map { ... }
.filter { ... }
.forEach { ... }
The result is functional code that is more concise with less syntactic noise.
FWIW, the documentation for Array, Dictionary, and Sequence all remind us of the limitations introduced by forEach, namely:
You cannot use a break or continue statement to exit the current
call of the body closure or skip subsequent calls.
Using the return statement in the body closure will exit only from
the current call to body, not from any outer scope, and won't skip
subsequent calls.
I recently ran across a use case where using forEachwas preferable in a tangible way to for in. Let's say you want to remove all sublayers from a layer. A statement such as the below doesn't work as you need to unwrap the [CALayer]
for layer in self.videoContainerView.layer.sublayers!
If sublayers are nil, you will get a crash. This forces you to check to see if there are sublayers first. However, a forEach makes this much simpler as in the following:
self.videoContainerView.layer.sublayers?.forEach { $0.removeFromSuperlayer() }
They are more or less interchangeable, but there are two important differences.
break/continue only work in a for .. in
return in forEach will exit the closure, but will not halt the iteration.
The reason for this is that for .. in is a special form in the language (which allows break and continue to work as you expect). It is something that you can't implement in an identical way using the language itself.
However, forEach is not a special form and can be re-implemented identically by writing it as a function.
extension Sequence {
func myOwnForEach(_ body: (Self.Element) throws -> Void) rethrows {
let it = Self.makeIterator()
while let item = it.next() {
body(item)
}
}
}
In addition to above answers one more reason that differentiates for loop from forEach is that with for loop we can also chose to implement that logic using where based pattern matching instead, like
for adBanner in adBanners where !adBanner.isLoading {
The above kind of control flow related features are what makes for loops so powerful, but if we don’t need that level of control, using a call to forEach might give us slightly simpler-looking code.
So in short using a for loop gives us a much greater degree of control over an iteration

Swift basic expression

I'm very new to swift, but proficient in other languages like Java, JavaScript, C, ... I'm lost with Swift syntax when it comes to create expressions. Look at this basic example where I just try to find out if one string is contained into another by calling String.rangeOfString that returns an Optional Range (Range?)
This works as expected:
let LEXEMA:String="http://"
let longUrl:String="http://badgirls.many/picture.png"
let range=longUrl.rangeOfString(LEXEMA);
if (range? != nil) {
// blah
}
Now I'm trying to combine the expression inside the if, something like:
if (longUrl.rangeOfString(LEXEMA)? !=nil) {
// blah
}
But I always get syntax errors, the above yields a "Expected Separator" and can't understand why. Done some more tests:
if (absolutePath.rangeOfString(URL_LEXEMA) !=nil) { }
Expected Separator before "!"
if absolutePath.rangeOfString(URL_LEXEMA) !=nil { }
Braced block of statements is an unused closure
What am I doing wrong?
If you’re coming from other like Java, you might be thinking of optionals like pointers/references, and so used to equating them to nil and if non-nil, using them. But this is probably going to lead to more confusion. Instead, think of them like a container for a possible result, that you need to unwrap to use. if let combines the test and unwrapping operation.
With this in mind, here’s how you could adapt your code:
let LEXEMA: String="http://"
let longUrl: String="http://badgirls.many/picture.png"
if let range = longUrl.rangeOfString(LEXEMA) {
// use range, which will be the unwrapped non-optional range
}
else {
// no such range, perhaps log an error if this shouldn’t happen
}
Note, that ? suffixing behaviour you were using changes in Swift 1.2 so even the code in your question that compiles in 1.1 won’t in 1.2.
It’s possible that sometimes you are whether there was a value returned, but you don’t actually need that value, just to know it wasn’t nil. In that case, you can compare the value to nil without the let:
if longUrl.rangeOfString(LEXEMA) != nil {
// there was a value, but you don't care what that value was
}
That said, the above is probably better expressed as:
if longUrl.hasPrefix(LEXEMA) { }
For starters:
You don't need parenthesis with if statements unless you have nested parenthetical subexpressions that require it.
You don't need to specify the type on the left side of the = of a let or var declaration if Swift can figure it out from the right side of the =. Very often Swift can figure it out, and you can tell that Swift can figure it out, so you can avoid that redundant clutter.
You do need to specify the type if Swift cannot figure out the type from
the right side. Example:
For example, consider the following lines:
let LEXEMA = "http://"
let longUrl = "http://badgirls.many/picture.png"
Swift can figure out that they're strings.
Similarly for this function or class that returns a UIView:
var myView = ViewReturningClassOrFunc()
Consider this:
#IBOutlet var myView : UIView!
In the above line, Swift cannot figure out ahead of time it will be assigned a UIView, so you have to provide the type. By providing a ! at the end you've made it an implicitly unwrapped optional. That means, like ?, you're indicating that it can be nil, but that you are confident it will never be nil at the time you access it, so Swift won't require you to put a ! after it when you reference it. That trick is a time saver and big convenience.
You should NOT add the ? to the line:
if (longUrl.rangeOfString(URL_LEXEMA) !=nil) {
As another answer pointed out, you're missing the let.
if let longUrl.rangeOfString(URL_LEXEMA) {
println("What do I win? :-)")
}
swift is case sensitive language. you need to check about whitespaces as well
if longUrl.rangeOfString(LEXEMA) != nil {
//your condition
}
there should be space between statement != nil
Just add a space between != and nil like:
if longUrl.rangeOfString(LEXEMA) != nil {
// blah
}
I tested your code in playground, an error of Expected ',' separator reported.
And do not forget the rules that 1s and 0s and Airspeed Velocity said.

How does Apple's new programming language Swift handle blocks and asynchronous requests?

C.f. Apple's website page on Swift: https://developer.apple.com/swift/
Are there blocks in Swift like in objective-c? How are they created and called?
How would do an asynchronous request in Swift?
Is it easy to create block related memory leaks in swift? If yes, how would you avoid them?
The Swift equivalent of an (Objective-)C block is called a closure. There's a whole chapter about them in The Swift Programming Language book.
Depending on the context where you use a closure, you can declare/use it with very concise syntax. For example, a method that takes a completion handler whose signature is (success: Bool, error: NSError) - > Void can be called like this:
someMethod(otherParameters: otherValues, completionHandler:{ success, error in
if !success { NSLog("I am a leaf on the wind: %#", error) }
})
There's also a trailing closure syntax that reads nicely in cases where a closure essentially provides flow control. And you can drop the parameter names when you want to be really brief (at some cost to readability, but that's okay in some obvious cases like the below). Often a return statement is implicit, too.
myArray.sort { $0 < $1 }
let squares = myArray.map { value in
value * 2
}
Swift itself doesn't have anything for asynchronous requests, so you use existing API for that. You can use the trailing closure syntax, though:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
// do some async stuff
NSOperationQueue.mainQueue().addOperationWithBlock {
// do some main thread stuff stuff
}
}
In most cases, you don't need to worry about creating reference cycles with Swift closures the way you do with ObjC blocks. To put it simply, the capture semantics are similar enough to "just work" the way you want it to for most stuff, but different enough that the common patterns for block/closure uses (e.g. dispatch to background/main thread and referencing self's properties) don't cause cycles.
Cycles are still possible, though, and there is a solution for them. This answer's a bit long already, so check out Strong Reference Cycles for Closures in the docs for the complete explanation.
Blocks in Swift are called closures. They operate much the same as blocks (though are more flexible, and operate in more places). Reference cycles are possible with closures in Swift, and can be avoided with closure capture lists.
“Swift provides an elegant solution to this problem, known as a closure capture list. However, before you learn how to break a strong reference cycle with a closure capture list, it is useful to understand how such a cycle can be caused”
Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks. https://itun.es/us/jEUH0.l
As I said in another question, you have many ways offered to pass a block equivalent to function in Swift.
I found three.
To understand this I suggest you to test in playground this little piece of code.
func test(function:String -> String) -> String
{
return function("test")
}
func funcStyle(s:String) -> String
{
return "FUNC__" + s + "__FUNC"
}
let resultFunc = test(funcStyle)
let blockStyle:(String) -> String = {s in return "BLOCK__" + s + "__BLOCK"}
let resultBlock = test(blockStyle)
let resultAnon = test({(s:String) -> String in return "ANON_" + s + "__ANON" })
println(resultFunc)
println(resultBlock)
println(resultAnon)
Update: There are 2 special cases to the Anonymous function.
The first is that function signature can be inferred so you don't have to rewrite it.
let resultShortAnon = test({return "ANON_" + $0 + "__ANON" })
The second special case works only if the block is the last argument, it's called trailing closure
Here is an example (merged with inferred signature to show Swift power)
let resultTrailingClosure = test { return "TRAILCLOS_" + $0 + "__TRAILCLOS" }
Finally, as an example:
Using all this power what I'd do is mixing trailing closure and type inference (with naming for readability)
PFFacebookUtils.logInWithPermissions(permissions) {
user, error in
if (!user) {
println("Uh oh. The user cancelled the Facebook login.")
} else if (user.isNew) {
println("User signed up and logged in through Facebook!")
} else {
println("User logged in through Facebook!")
}
}