Swift if statement not returning value - macos

In the block of Code below, String(quakeTsunamiWarning) isn't returning with any response, and is giving the error Use of Unresolved Identifier 'quakeTsunamiWarning'
I'd like to apologise in advance if something is obviously wrong or blatantly obvious, but i'm still rather new when it comes to Programming with Swift. (Going off free tutorials I can find on Google here, as I don't have the funds to pay for a course or paid tutorial)
var quakeTsunami = 0
func newQuake() -> Void {
if quakeTsunami == 0 {
var quakeTsunamiWarning = "False"
} else if quakeTsunami == 1 {
var quakeTsunamiWarning = "True"
} else {
var quakeTsunamiWarning = "N/A"
}
println(String(quakeTsunamiWarning))
}
I've removed all the other code from the example, for sake of keeping this post relatively small, but here's a link to a gist if you want the full document. https://gist.github.com/kurisubrooks/0ba9f7547ee960657dec
Thanks in advance!

You have three separate quakeTsunamiWarning variables, each only visible inside the innermost containing {}. Move it outside the if/else structure:
var quakeTsunamiWarning: String
if quakeTsunami == 0 {
quakeTsunamiWarning = "False"
} …
And you don't need to convert it to String since it already is a String.

Related

Is there some syntactic sugar for matching on deeply nested Option and Result chains?

I am issuing calls that return an Option that contains a Result which contains another Option that contains custom variants.
I am only ever interested in a specific chain of variant results like this:
if let Some(Ok(Some(CustomVariant(Some(value))))) = expr {
// handle value case
}
This is getting quite verbose and not really helpful, since I actually treat it as a single Result in all of my code. Can I somehow alias this code so that instead of writing the entire chain of Options and Results I can do something similar to:
alias TheCase(value) = Some(Ok(Some(CustomVariant(Some(value))));
if let TheCase(value) = expr {
//handle value
}
You don't need such an alias, just use a function to retrieve the one case you want:
fn oneCaseICareAbout(value: &Option<Result<Option<Foo>, Bar>>) -> Option<&Foo> {
if let Some(Ok(Some(CustomVariant(Some(value)))) = value {
Some(value)
} else {
None
}
}
if let Some(value) = oneCaseICareAbout(expr) {
//handle value
}
I would however consider refactoring your code not to use such a type. Option<Result<_, _>> is already a red flag, but Some(Ok(Some(CustomVariant(Some(…)))) is just on the edge of insanity!

Problems checking to see if a value exists in Swift 2

I'm writing a quiz app and there is a table view to add a subject (The name is saved to core data) and when you select an index path it passes the subject to a detail view controller (this works just fine on its own) but what I'm having trouble with is checking to see if any cards exists (the subject entity has an NSOrderedSet of "Cards"). I keep getting a crash on my two attempts, I've done this in swift before with relationships and tableViews and it's always been fine so I'm not sure what the problem is here. Thank you for the help like always!
My first attempt, although it says "catch block is unreachable because no errors are thrown in do block", it crashes with "Bad Instruction" on the line after "do"
do {
if let firstCard = self.subject?.cards![0] as? Card {
self.currentCard = firstCard
}
} catch {
}
My second attempt, it crashes on the first line
if let firstCard = self.subject?.cards![0] as? Card {
self.currentCard = firstCard
}
My third attempt
if self.subject!.cards != nil {
self.currentCard = self.subject!.cards![0] as! Card
}
My fourth attempt, unwrapping both the subject property and subject, it not rings out self.subject.cards but still crashes
if let firstCard = self.subject!.cards?[0] as? Card {
self.currentCard = firstCard
}
Where the properties are declared
var draggableView = DraggableView!()
var subject : Subject?
var currentCard : Card?
var cardArray = [Card]()
The update with subject method (works perfectly, but put it here just for reference), the subject is passed from another class and this method called at the top of view did load.
func updateWithSubject(subject: Subject) {
if let subject = self.subject {
self.subject = subject
}
}
In all four of your attempts, you do a "forced" unwrapping (!) at some point, which is to be generally avoided. Also, you attempt to explicitly accessing index 0 in your NSOrderedSet; if the set is empty, accessing [0] will yield a runtime exception.
Instead, you could use the .array representation of the NSOrderedSet and use the .first (optional) property of array for a safe access test:
if let firstCard = self.subject?.cards?.array.first ...
I think there's some awkwardness going on in your updateWithSubject method. You're checking if there's a subject already initialized before assigning to it. If that's in your viewDidLoad and only there, the assignment will never happen. The forced unwrapping that follow will surely fail after.

How do you convert optional text input to Int in Swift 2, Xcode 7 beta using if let - toInt does not work

I'm having trouble converting optional input String to Int in order to do calculations on it.
let odoField = UITextField() // allows entry of text to iOS field
odoField.text = "12500" // simulated input
let odoString = odoField.text
// now here is where I get trouble...
if let odoInt = odoString.toInt() {
distance = Double(odoInt)
}
Apparently the toInt suffix is no longer part of Swift. I have tried the following:
if let odoInt = Int(odoString)() {
But then I get the error "Optional type String? is not unwrapped" and a suggestion to put a ! or ?, as in:
if let odoInt = Int(odoString!)() {
But then I STILL get the euro about unwrapping, with the suggestion that I add yet another !, then when I do that, another error that I get rid of the parens, like this:
if let odoInt = Int(odoString!)! {
And then I get ANOTHER error that "Initializer for conditional binding must have Optional type, not 'Int'."
I'm trying to create conditional unwrapping, here.
Help!
First thing to understand is that UITextField.text returns an optional string, so in your code, odoString is of type String?. Also, keep in mind that the Int constructor takes a String, not a String? so you have to unwrap the String? before you can use it. Just putting a ! after the variable (as in Int(odoString!)) will crash your app if the odoString is nil. Better would be something like this:
if let s = odoString, odoInt = Int(s) {
// odoInt is of type Int. It is guaranteed to have a value in this block
}
I've tested Daniel T's answer and it worked.
I have a situation where I want to get the result of a text field back as an optional Int. You can extend this to cover your case using the following code:
let odoInt = odoField.text != nil ? Int(odoField.text!) : nil
if let odoInt = odoInt {
// Use unwrapped odoInt here
}
Another option - for a more compact solution - is to use a flatMap:
let number = odoString.flatMap { Double($0) } ?? 0.0
In fact, it appears that the answer in Swift 2 (Xcode 7 beta 6) is simpler than anything above. The code does not choke on a nil value for odoString when I do e.g. the following:
if let odoInt = Int(odoString!) {
distance = Double(odoInt)
}
I therefore surmise, barring deeper knowledge to the contrary, that the compiler does treat this as "if the statement is True (the right side is valid), then define and initialize the variable, and continue with execution." I welcome further feedback. This does render unnecessary a lot of the extra code that is suggested above.

Swift: typecasting in a for loop

I'm a noobie in Swift. I'm trying to iterate over SKNodeTree and check if there are scary monster Nodes here. However I cannot figure out how to typecase the for loop. I have understood that this would be possible with "as" clause.
By the way, is comparing strings with == ok in Swift?
for monsterNode in self.children{
if (monsterNode.name? == "scary") {
println("scary monster here")
}
}
Comparing strings can be done by using == instead of isEqualToString, so thats fine. Your code should be like this:
for monsterNode in self.children as [SKNode] {
if (monsterNode.name? == "scary") {
println("scary monster here")
}
}
You can submit your cast inside the brackets []

How to replace lambda written in Where clause of Linq with equivalent delegate

I have an Query expression that uses a predicate type and lambda expression.
I am getting desired result with this. But I am not clear with how this expression is getting evaluated.
I tried to break this lambda expression by creating delegate and replacing condition under Where with delegate type.
If I have to rewrite the same thing with writing a delegate instead of anonymous type. What will be the syntax. How the delegate will be return for the same.
if (((DataTable)dgvAssignedRpm.DataSource).AsEnumerable()
.Where(row => row.Field<long>("FK_RPM_BTN_SETTING_ID") == objRpmButtonHolder.RpmSettingId).Count() > 1)
{
List<DataRow> listPkgBtnSettings = SearchForExistingSettingId();
}
void MethodSignature(...)
{
...
if (((DataTable)dgvAssignedRpm.DataSource).AsEnumerable()
.Where(RowCondition)
{
List<DataRow> listPkgBtnSettings = SearchForExistingSettingId();
}
...
}
// Where want a Func<T,bool> parameter
// T is the first parameter type (DataRow here)
// bool represents the return value
bool RowCondition(DataRow row)
{
return row.Field<long>("FK_RPM_BTN_SETTING_ID") == objRpmButtonHolder.RpmSettingId).Count() > 1
}
I assume the correct delegate replacement would be:
if (((DataTable)dgvAssignedRpm.DataSource).AsEnumerable().Where(
delegate(DataRow row) {
return (row.Field<long>("FK_RPM_BTN_SETTING_ID") == objRpmButtonHolder.RpmSettingId.Count() > 1);
}))
{
List<DataRow> listPkgBtnSettings = SearchForExistingSettingId();
}
But it's morning for me, so forgive me if I'm a bit off.
What the where desires is to give a DataRow as a parameter and a bool to return. You could just about fill in anything in the lambda or delegate, as long as it matches these requests.
To your question why it requests Func<> and how it works. The statement you're using is LINQ, so I found you a reference regarding this which can probably explain it better than me:
http://blogs.msdn.com/b/mirceat/archive/2008/03/13/linq-framework-design-guidelines.aspx
But yeah, the last type here in the Func<> is what it returns. (However, I can still recommend using the Lambda expression, as it's pretty clean, neat and serves the Func<> best.
(Also, look at what intellisence gives you when you write "new Func<....", it should give you a good idea of what Func wants and can do!)
Hope I was of help.

Resources