Guard with trailing closure - Swift Syntax - swift

Let's say, I have a function which takes a closure as its last parameter, so it can be shortened to something like this:
let reminder = reminders.first { (reminder) -> Bool in
return reminder.mealIdentifier == mealIdentifier
}
Awesome! Now let's say I want to put this in a guard statement, like this:
guard let reminder = reminders.first { (reminder) -> Bool in
return reminder.mealIdentifier == mealIdentifier
} else {
continue
}
The moment I do this, the compiler starts screaming. The fix is to use no trailing closure short syntax when calling the function, but it's cumbersome as the default auto-completion by Xcode doesn't have an option to NOT do trailing closures short syntaxes when your last parameter is a closure:
guard let reminder = reminders.first(where: { (reminder) -> Bool in
return reminder.mealIdentifier == mealIdentifier
}) else {
continue
}
Is there anything I'm missing here? Or is there a way to somehow have Xcode do autocompletion without the shortened syntax?

Or is there a way to somehow have Xcode do autocompletion without the shortened syntax?
Xcode is quite smart. It chooses the non-trailing closure version if you do the auto completion in a control flow statement that needs a {. For example, if I type:
guard let a = reminders.first
The auto complete shows:
If I choose the highlighted option, I get:
guard let a = reminders.first(where: <#T##(String) throws -> Bool#>)
If I then press enter, I get:
guard let a = reminders.first(where: { (<#String#>) -> Bool in
<#code#>
})
It doesn't turn it into a trailing closure, as long as you autocomplete within a guard/if statement.

Related

Why does my code work on Playgrounds but not CoderPad?

I have a very simple func in Xcode playgrounds which works when I run it. But when i try to run the same code in CoderPad it gives me the following error Solution.swift:18:1: warning: result of call to 'isPalindrome(word:)' is unused
isPalindrome(word:"racecar")
Here is the code
import Foundation
func isPalindrome(word: String) -> Bool{
var oddCharacters: Set<Character> = []
for char in word {
if oddCharacters.contains(char){
oddCharacters.remove(char)
}else{
oddCharacters.insert(char)
}
}
return oddCharacters.count <= 1
}
isPalindrome(word:"racecar")
I really do not understand why this is happening.
Try this:
import Foundation
func isPalindrome(word: String) -> Bool{
var oddCharacters: Set<Character> = []
for char in word {
if oddCharacters.contains(char){
oddCharacters.remove(char)
}else{
oddCharacters.insert(char)
}
}
return oddCharacters.count <= 1
}
print(isPalindrome(word:"racecar"))
all you had to do was print it, hope this helped
That means, that the "left-hand-side" result of the call to your function isPalindrome(word: "racecar") is unused ("wasted").
It seems that for a debugging, testing, try-out environment like a Playground it's just okay to find out the result of this call (true) without storing it inside a variable. However, when doing that in other development environments, the compiler will be complaining about that. I can give you four options that would prevent the error from being thrown, just to give you a better idea of why the compiler is complaining:
If you want to use it in your further code below, just store the result and change your calling line to let isPalindrome = isPalindrome(word: "racecar"). But if you don't use it, the compiler will give you a warning again saying that you're never using your isPalindrome variable... --> Option 2
If you don't need the result, you can also just say: _ = isPalindrome(word: "racecar"). That will explicitly tell the compiler "bro, it's okay if the result is just ignored". It wouldn't make much sense for this function, though.
You can add the #discardableResult keyword prior to your function declaration, so it would say: #discardableResult func isPalindrome(word: String) -> Bool { ... That would kinda just silence your thrown error and like option 2 just tell the compiler that it's okay to just ignore the result of this function.
Just use the result in any way like:
if isPalindrome(word: "racecar") {
// do something
} else {
// do something else
}
// or
print("racecar is a palindrome: \(isPalindrome(word: "racecar")")
and everything will just be fine. I hope that helps you!

Simplifying this Swift 4 logic

Complete newb to Swift 4 here. How can the following be more compactly written in Swift?
if myVar != nil {
if !myVarList.contains(myVar!) {
myVarList.append(myVar!)
}
}
I tried searching for examples of guard but couldn't find anything. I think Swift allows me to more compactly deal with the nil checking, but not sure how to go about it when combined with the nested conditional.
Just use if let to conditional unwrap the optional and do the other check in the same line, the comma represents a boolean AND operator
if let item = myVar, !myVarList.contains(item) {
myVarList.append(item)
}
If an (unwrapped) optional is going to be used after the check never write != nil
guard is only useful if an evaluation to false exits the scope
func foo() {
guard let item = myVar, !myVarList.contains(item) else { return }
myVarList.append(item)
}

Binary operator '>' cannot be applied to two 'String?!' operands

So I have a project, that builds fine. but hen I want to Archive it it throws this error on this line of code:
let pred = NSPredicate(format: "%K in %#", "categoryID", selectedCategoryIDs!)
let selectedAlmanacEntries = almanacEntries.filter { pred.evaluate(with: $0) }.sorted(by: { ($0 as AnyObject).title > ($1 as AnyObject).title })
this hasn't been an issue before (Earlier releases).
Have tried restarting Xcode and cleaning the project before.
Any hints appreciated.
(Xcode 8, Swift 3)
Swift 5
you can simply unwrap optional by this way
let selectedAlmanacEntries = selectedAlmanacEntries.sorted {
var isSorted = false
if let first = $0.title, let second = $1.title {
isSorted = first < second
}
return isSorted
}
?! is a really great construction, isn't it? Perfectly sums up the reaction whenever you see it in an error message.
Anyway, in Swift, you're probably better off casting to the appropriate type that these objects should belong to instead of AnyObject. If you must duck type, then you should be aware that every time Swift calls a method on AnyObject, it gains a level of optionality due to the fact that Swift can't verify that the object actually responds to the message. So you will have to deal with the optionals.
The other problem is that since there exist multiple classes in the frameworks that have properties named title, Swift has no way of knowing which one to use. And some of them have different signatures; for example, NSButton has a title property that is typed as String, NSStatusItem has a title property that is typed as String?, and NSWindowTab has a title property that is typed as String!. Which one the compiler picks is a bit of a luck of the draw, which is why random chance can make it behave differently from compile to compile. So you need to help the compiler out by telling it what type to expect.
So, something like this can work:
let selectedAlmanacEntries = almanacEntries.filter { pred.evaluate(with: $0) }.sorted(by: {
guard let first: String = ($0 as AnyObject).title else { return false }
guard let second: String = ($1 as AnyObject).title else { return true }
return first > second
})
Or, if your heart is set on a long one-liner as in the original:
let selectedAlmanacEntries = almanacEntries.filter { pred.evaluate(with: $0) }.sorted(by: { (($0 as AnyObject).title as String?) ?? "" > (($1 as AnyObject).title as String?) ?? "" })
I'd really recommend casting to the actual type instead, though.

Using guard keyword

I have encountered numerous situations where a coder have used the guard keyword. And then later, in a seemingly almost identical situation the same coder in the same code does not use the guard keyword. I am aware that this may be a stupid question, so please don't bash it. When should I use the guard keyword and where shouldn't I?
Here is an example (there are many more). This is part of a script that is requesting data form an API.
//Here I am using guard
guard let json = json else {
//Now I am not using guard
if let error = error {
completion(.Failure(error))
} else {
//Error handling
}
return
}
Why not use the:
if let var1 = var1 {
//Keep on going
} else {
//Don't crash
}
syntax all the time instead of the guard syntax? At first glance it even seems to have more functionality, but I am certain that does not have to be the case.
One great benefit of the guard statement is that you know that if the condition is not satisfied then the execution flow gets stopped.
This is important for several reasons
Unwrapping
You can define unwrapped values which don't need a new scope { ... } to be available
func next(num:Int?) -> Int? {
guard let num = num else { return nil }
return num + 1
}
Readability
When you read the code you know that if the guard condition is not satisfied then the following lines won't be executed.
Semantics
You know a guard statement is there to check conditions required for the following block of code.
But I can replace every guard with an if
Sure. We could also replace every while and for with a goto in some languages. And we could always replace recursion with iteration (and viceversa).
But this doesn't necessarily means it is always a good idea.
Despite we can implement some behaviours with more then one programming "tool", we should still use the one that better fits that specific scenario.

Accessing a Dictionary using user input returning double value

I'd like the user to input a String to access a key in the dictionary which then returns its coupled value. I'm sure this isn't the only thing wrong with my code but trying to see if I have the right idea and hoping for some additional direction:
Main two issues are writing the correct syntax to connect the user input getInput() (String) inside the function callfunc planetAndTime()The function is passing my dictionary as a parameter.
My other issue is returning my function's double value. ->Double`
func getInput() -> String{
let kb: NSFileHandle = NSFileHandle.fileHandleWithStandardInput()
let inputData: NSData = kb.availableData
let strData = NSString(data: inputData, encoding:NSUTF8StringEncoding) as! String
return strData
}
/////////
let nameOfPlanetsAndTime:[String:Double] = ["Mercury":0.00000816,
"Venus":0.00044, "Mars":0.0000239, "Jupiter":0.00062, "Saturn":0.000204,
"Uranus":0.000289, "Neptune":0.000459, "Pluto":0.000794,
"Center of the Milky Way":25000.000000, "Earth's Cousin":1400.000000]
print("Choose planet")
func planetAndTime(nameOfPlanetsAndTime: [String:Double], userLocation:String) ->Double{
let userLocation = getInput()
if (nameOfPlanetsAndTime[userLocation] < 0){
print("Not a Valid Location, Please Try Again")}
else{
nameOfPlanetsAndTime[userLocation]!
print(nameOfPlanetsAndTime)
}
}
There are a few issues with your code that are due to a misunderstanding of how the Swift language works so I would recommend going through the official Swift documentation for some good examples of the Swift features. To give you a little head start however I will choose a section of your code. For example, instead of writing"
if (nameOfPlanetsAndTime[userLocation] < 0){
print("Not a Valid Location, Please Try Again")}
you can write
guard let planet = nameofPlanetsAndTime[userLocation] {
print("Not a Valid Location, Please Try Again")
return nil
}
return planet
and change the return type of your function to an optional Double. So the method signature would look like
func planetAndTime(nameOfPlanetsAndTime: [String:Double], userLocation:String) ->Double?
Understanding optionals is super important in the Swift "world" and I highly recommend taking a good look at how to use them. I hope this little example is helpful.
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html#//apple_ref/doc/uid/TP40014097-CH5-ID309