Immutable value never used in for in loop - swift

I'm learning Swift and have started a Playground in Xcode 9.2. I've got the following code and whilst it is running as expected, it's giving me an warning message. What does it mean? I tried searching elsewhere but I can't find out why it's returning a warning.
for myCounter in 1...3 {
print("My counter")
}
The warning:
Immutable value 'myCounter' was never used; consider replacing with '_' or removing it
I tried doing what it said, and it seemed to work and not return any warnings, but why would that make a difference?
for _ in 1...3 {
print("My counter")
}
What's the difference here and why does it cause this?

The warning is telling that you are not using myCounter for anything, when you don't care about something in Swift you use _ to tell the compiler that your intention is to not use that value.
The warnings would also go away if you started using the value:
for myCounter in 1...3 {
print("My counter: \(myCounter)")
}

Swift has a smart compiler which optimizes. You are assigning 1, 2, and 3 into variable storage, to no purpose; you never use that variable for anything. So that is a waste of time and storage space. Therefore the compiler warns you to try to get you to improve the program. You did. It stopped warning.

Related

How do I interpret swift (or general) closure in call stack in assembly?

class Assembly {
func getThis(value: Int) -> () -> () {
var a = value
return {
a += 1
print(a)
}
}
}
let assembly = Assembly()
let first = assembly.getThis(value: 5)
first()
first()
let second = assembly.getThis(value: 0)
second()
second()
first()
second()
gives value of:
6
7
1
2
8
3
I understand this is expected and I just want to understand how this works. I know the basics of how stack works in assembly. I think when getThis called, a new stack frame is pushed and allocate local variable a by assigning value.
But does this stack frame get popped? It looks like it does, because it returns a value means the function has finished. But on the other hand, if the stack frame is popped, the local variable on the stack frame is gone, means the a will be deallocated, obviously this isn't the case.
So how does this whole thing work?
There is a very large "gap" between Swift code and assembly code. The transformation between these two languages is vast, so I recommend you not to think "Oh wait, that wouldn't work in assembly!" because compilers are much smarter than you might think.
What basically happens here is, the closure retuned by getThis captures the local variable a. This means that a kind of "went inside" the closure. The closure now has state. This happens whenever you use self or a local variable in a closure.
How is this achieved at a low-level of abstraction? I am not really sure about how exactly the compiler works, but this kind of capturing of variables is usually done with a state machine of some kind. Therefore, your statement about a getting deallocated when getThis returns is probably not true. a will stay in memory, because it is retained by the closure. How does it do this? I can only tell you "compiler magic".
Anyway, how else do you want first to behave? Undefined behaviour? That doesn't sound Swifty. Resetting a to 0 every time you call first? That's no different from declaring a new variable again in first, is it? At the end of the day, it just seems like this "capturing" semantics is a useful thing to have in the language, so they designed Swift like so.

Get Around the "Initialization of immutable value 'variableName' was never used" Warning in Swift 3 Switch Statements

So I have some code that looks like this:
fileprivate func enumSwitchTime(_ optionalString: String?) {
if let nextEnumToSwitchOn = funcToGetEnum()
switch nextEnumToSwitchOn {
case .enumStateOne(let associatedEnumValue):
if let optionalString = optionalString {
//do stuff with both associatedEnumValue and optionalString
}
case .enumStateTwo...
.
.
.
}
}
However since Swift 3 (I'm using Xcode 8.1) I am getting the "Initialization of immutable value 'associatedEnumValue' was never used..." warning on the that first case.
I am still getting my toes wet in Swift, but so far I see no way around this. I can't do an underscore parameter in the case statement and then declare the associated enum value later, after the let optionalString = optionalString, or at least I haven't found any way of doing that.
It is just a warning, but I don't like warnings in my code. Any way around this?
Well, as it turns out this was an Xcode error/issue.
After cleaning my project and restarting Xcode multiple times, and the warning persisting, I posted the question here thinking I was missing something.
After Martin R said if the variable is used in any code path the warning shouldn't be there, I futzed around with the code, undid those changes, cleaned the project, restarted Xcode and FINALLY the warning went away.

Constant in viewDidLoad error

I am trying to make a simple addition program, but when I put my let function in the viewDidLoad, it gives me this error:
initialization of immutable value 'doMath' was never used; consider
replacing with assignment to '_' or removing it.
Here is the code
let doMath: (Int!, Int!) -> Int =
mathFunction(text1, text2)
}
What should I do?
This is something new in swift2 that is if you are not using the particular variable then replace it with _ or use that variable, that's why it suggests you to replace your variable name with _. This is mainly designed for reducing memory and CPU usage.
It is not an error. It is a warning.
initialization of immutable value 'doMath' was never used; consider replacing with assignment to '_' or removing
What this means is that you never use doMath after declaring it. As soon as you actually use doMath in your code, the warning will go away.
Yes, as stated it is a warning letting you know that you have declared a variable that has not been used either before or after the declaration. The warning message suggests that you replace the variable (doMath) with a simple (_) as doMath is not used outside of the declaration.
Your options are to ignore the warning message, or to use it outside of the declaration.
You could also set up the function completely different if you are only looking for a simple addition function.
var firstNumber = 4
var secondNumber = 6
var doMath = (firstNumber + secondNumber)
print(doMath)

Bad Access in `top_level_code` when I set instance variable

Ok, this is an odd error and it's taken me many hours to track down the exact location (although the cause remains unknown). The error only occurs on 64-bit devices. In other words, it works fine on my iPhone 5, but crashes on my iPhone 6 Plus.
Essentially, I have a private variable in a class:
class Manager {
private lastUpdated:NSDate?
}
Initially, it's not set. This class retrieves messages from a server and then sets the lastUpdated variable to NSDate().
private func checkForNewMessages(complete:Result<[Message]> -> ()) {
self.server.userMessages(u, fromDate: self.lastUpdated) { result in
result.onSuccess { messages in
self.insertMessages(messages)
self.lastUpdated = NSDate()
complete(Result(messages))
}
result.onError { err in complete(Result(err)) }
}
}
I've deleted extraneous code, but nothing inside the code path that's crashing (just stuff around it)
Note: I'm using a Result enum. For more info about this kind of enum, this article is pretty good at explaining it: Error Handling in Swift.
The first time the manager retrieves messages, everything works fine and the lastUpdated value is set correctly. If I then try to retrieve messages again, the app crashes when it tries to set self.lastUpdated = NSDate().
I can get it to work if I delay the assignment by using GCD, dispatch_after. But I don't want to do that.
Does anyone have any idea why this is occurring?
Update
This is only occurring when I assign a NSDate. It's not occurring if I try to set another object type (Int, Bool, String) etc.
The crash occurs if I change the stored variable to NSTimeInterval and attempt to set it from NSDate.timeIntervalSinceReferenceDate()
The crash occurs if I store an array of updates and attempt to simply append a new date to that array.
The crash occurs if I attempt to set lastUpdated before the server is called rather than in the callback.
The crash occurs if I wrap NSDate in another class.
The crash occurs is I set lastUpdated in a background thread
The crash doesn't occur if I println(NSDate()) (removing the assignment)
Ok, it took me numerous hours but I finally figured it out.
This will be a little difficult to explain and I'm not certain I fully understand what is going on. The error actually occurred in the Server class that was making the request. It took the lastUpdated date, converted it to a string and then sent that up to the server. The first run, there was no date, so no issue. In the second run, it took the date and used a date formatter to convert it to a string. However, I thought that stringFromDate returned an Optional. It does not. Normally, the compiler would warn me if I attempted to unwrap something that wasn't an option. However, I use Swift's functional aspects to use Infix operators to unwrap and conditionally pass the unwrapped value to another function, which can then pass it's value on. It allows me to chain unwraps together so I can avoid "nested if-let hell".
Very simple but powerful:
infix operator >>? { associativity left}
func >>? <U,T>(opt: T?, f: (T -> U?)) -> U? {
if let x = opt {
return f(x)
}
return nil
}
Note that the function must return an Optional. For some reason, the Swift compiler missed the fact that stringFromDate did not return an optional and so it didn't warn me. I'm not sure why that is, it's certainly warned me before:
if let update = fromDate >>? self.dateFormatter.stringFromDate {
This fails, but not immediately
Unwrapping a non-optional value doesn't immediately result in a crash, error or anything apparently. I successfully used the date string to send and receive data from the server. I'm not certain why unwrapping a non-optional string would later result in a crash and that only when I attempted to set the instance variable that of the backing NSDate object the string was generated from. I think somehow, unwrapping a non-optional screwed up some pointers, but not necessarily the pointer to the unwrapped object. I think the crash itself has to do with Swift attempting to release or dealloc the original instance variable (lastUpdated) when a new one is set, but found the memory address messed up. I think only a Apple Swift engineer could tell me what actually happened, but perhaps there are clues here to how Swift works internally.

Treating a forced downcast as optional will never produce 'nil'

I've been playing around with Swift and discovered that when down casting an object to be inserted into a dictionary, I get a weird warning: Treating a forced downcast to 'String' as optional will never produce 'nil'. If I replace as with as? then the warning goes away.
func test() -> AnyObject! {
return "Hi!"
}
var dict = Dictionary<String,String>()
dict["test"]=test() as String
Apple's documentation says the following
Because downcasting can fail, the type cast operator comes in two different forms. The optional form, as?, returns an optional value of the type you are trying to downcast to. The forced form, as, attempts the downcast and force-unwraps the result as a single compound action.
I'm unclear as to why using as? instead of as is correct here. Some testing reveals that if I change test() to return an Int instead of a String, the code will quit with an error if I continue using as. If I switch to using as? then the code will continue execution normally and skip that statement (dict will remain empty). However, I'm not sure why this is preferable. In my opinion, I would rather the program quit with an error and let me know that the cast was unsuccessful then simply ignore the erroneous statement and keep executing.
According to the documentation, I should use the forced form "only when you are sure that the downcast will always succeed." In this case I am sure that the downcast will always succeed since I know test() can only return a String so I would assume this is a perfect situation for the forced form of down casting. So why is the compiler giving me a warning?
Let's take a closer look at your last line, and explode it to see what's happening:
let temporaryAnyObject = test()
let temporaryString = temporaryAnyObject as String
dict["test"] = temporaryString
The error is on the second line, where you are telling the compiler to enforce that temporaryAnyObject is definitely a String. The code will still compile (assuming you don't treat warnings as errors), but will crash if temporaryAnyObject is not actually a String.
The way as works, with no ?, is basically saying "from now on, treat the result of this expression as that type IF the result is actually of that type, otherwise we've become inconsistent and can no longer run.
The way as? works (with the ?) is saying "from now on, treat the result of this expression as that type IF the result is actually of that type, otherwise the result of this expression is nil.
So in my exploded example above, if test() does return a String, then the as downcast succeeds, and temporaryString is now a String. If test() doesn't return a String, but say an Int or anything else not subclassed from String, then the as fails and the code can no longer continue to run.
This is because, as the developer in complete control, you told the system to behave this way by not putting the optional ? indicator. The as command specifically means that you do not tolerate optional behavior and you require that downcast to work.
If you had put the ?, then temporaryString would be nil, and the third line would simple remove the "test" key/value pair from the dictionary.
This might seem strange, but that's only because this is the opposite default behavior of many languages, like Obj-C, which treat everything as optional by default, and rely on you to place your own checks and asserts.
Edit - Swift 2 Update
Since Swift 2, the forced, failable downcast operator as has been removed, and is replaced with as!, which is much Swiftier. The behavior is the same.
You can solve this warning from two angles. 1. The value you return 2. The type that you are expected to return. The other answer speaks about the 1st angle. I'm speaking about the 2nd angle
This is because you are returning a forced unwrapped and casted value for an optional. The compiler is like, "If you really want to just force cast all optionals then why not just make the expected return parameter to be a non-optional"
For example if you wrote
func returnSomething<T> -> T?{ // I'm an optional, I can handle nils SAFELY and won't crash.
return UIViewController as! T // will never return a safe nil, will just CRASH
}
Basically you told yourself (and the compiler) I want to handle nils safely but then in the very next line, you said nah, I don't!!!
The compiler would give a warning:
Treating a forced downcast to 'T' as optional will never produce 'nil'
An alternative is to remove the ?
func returnSomething<T>() -> T{ // I can't handle nils
return UIViewController() as! T // I will crash on nils
}
Having that said, likely the best way is to not use force cast and just do:
func returnSomething<T>() -> T?{ // I can handle nils
return UIViewController() as? T // I won't crash on nils
}
It looks like there is bug open about this warning fo some years now...
https://bugs.swift.org/browse/SR-4209 So it shows even in situations where it is obvious what you are doing and right.