I know that if a variable is declared it is easy to test whether or not it is null, but I can't find a way to work out if a variable is declared at all. What I need is:
If variable is declared:
var i:Int
if [i is declared] {
// returns true
}
If variable is not declared:
if [i is declared] {
// returns false (but does not crash)
}
Use case: I am writing an app to teach people Swift. I want to be able to evaluate their code and make sure it is correct. So my instruction might be 'create a variable called i and set it equal to 1' and I want to test if they have done that correctly. In PHP I can do isset($i), I need an equivalent in Swift. I can't use if i == null because as simpleBob says that will crash if is not defined.
Thanks in advance!
Rob
If you are just looking to see if there is a variable by a certain name in a class, you could simply start typing the variable name in that class and it should auto-populate.
However, as simpleBob mentioned, the code will not compile if variables are used before their declaration.
Updated
I am not sure how you have the users entering data, however, if they are entering it into a UITextView, you could grab the .containsString property and see if they put in the variable as you asked.
if myTextView.text.containsString("var i = 1")
{
print("They entered it correctly.")
}
else
{
// Do Something
}
You could even chain those to include other variations they would use.
I hope this helps.
Related
I have some code and when I run it produces an error, saying:
NoSuchMethod: the method 'XYZ' was called on null
What does that mean and how do I fix it?
Why do I get this error?
Example
As a real world comparison, what just happened is this conversation:
Hey, how much gas is left in the tank of the car?
What are you talking about, we don't have a car.
That is exactly what is happening in your program. You wanted to call a function like _car.getGasLevel(); but there is no car, the variable _car is null.
Obviously, in your program it might not be a car. It could be a list or a string or anything else really.
Technical explanation
You are trying to use a variable that is null. Either you have explicitly set it to null, or you just never set it at all, the default value is null.
Like any variable, it can be passed into other functions. The place where you get the error might not be the source. You will have to follow the leads from the actual null value to where it originally came from, to find what the problem is and what the solution might be.
null can have different meanings: variables not set to another value will be null, but sometimes null values are used by programmers intentionally to signal that there is no value. Databases have nullable fields, JSON has missing values. Missing information may indeed be the information itself. The variable bool userWantsPizzaForDinner; for example might be used for true when the user said yes, false when the user declined and it might still be null when the user has not yet picked something. That's not a mistake, it's intentionally used and needs to be handled accordingly.
How do I fix it?
Find it
Use the stack trace that came with the error message to find out exactly which line the error was on. Then set a breakpoint on that line. When the program hits the breakpoint, inspect all the values of the variables. One of them is null, find out which one.
Fix it
Once you know which variable it is, find out how it ended up being null. Where did it come from? Was the value never set in the first place? Was the value another variable? How did that variable got it's value. It's like a line of breadcrumbs you can follow until you arrive at a point where you find that some variable was never set, or maybe you arrive at a point where you find that a variable was intentionally set to null. If it was unintentional, just fix it. Set it to the value you want it to have. If it was intentional, then you need to handle it further down in the program. Maybe you need another if to do something special for this case. If in doubt, you can ask the person that intentionally set it to null what they wanted to achieve.
simply the variable/function you are trying to access from the class does not exist
someClass.xyz();
above will give the error
NoSuchMethod: the method 'xyz' was called on null
because the class someClass does not exist
The following will work fine
// SomeClass created
// SomeClass has a function xyz
class SomeClass {
SomeClass();
void xyz() {
print('xyz');
}
}
void main() {
// create an instance of the class
final someClass = SomeClass();
// access the xyz function
someClass.xyz();
}
I have some code and when I run it produces an error, saying:
NoSuchMethod: the method 'XYZ' was called on null
What does that mean and how do I fix it?
Why do I get this error?
Example
As a real world comparison, what just happened is this conversation:
Hey, how much gas is left in the tank of the car?
What are you talking about, we don't have a car.
That is exactly what is happening in your program. You wanted to call a function like _car.getGasLevel(); but there is no car, the variable _car is null.
Obviously, in your program it might not be a car. It could be a list or a string or anything else really.
Technical explanation
You are trying to use a variable that is null. Either you have explicitly set it to null, or you just never set it at all, the default value is null.
Like any variable, it can be passed into other functions. The place where you get the error might not be the source. You will have to follow the leads from the actual null value to where it originally came from, to find what the problem is and what the solution might be.
null can have different meanings: variables not set to another value will be null, but sometimes null values are used by programmers intentionally to signal that there is no value. Databases have nullable fields, JSON has missing values. Missing information may indeed be the information itself. The variable bool userWantsPizzaForDinner; for example might be used for true when the user said yes, false when the user declined and it might still be null when the user has not yet picked something. That's not a mistake, it's intentionally used and needs to be handled accordingly.
How do I fix it?
Find it
Use the stack trace that came with the error message to find out exactly which line the error was on. Then set a breakpoint on that line. When the program hits the breakpoint, inspect all the values of the variables. One of them is null, find out which one.
Fix it
Once you know which variable it is, find out how it ended up being null. Where did it come from? Was the value never set in the first place? Was the value another variable? How did that variable got it's value. It's like a line of breadcrumbs you can follow until you arrive at a point where you find that some variable was never set, or maybe you arrive at a point where you find that a variable was intentionally set to null. If it was unintentional, just fix it. Set it to the value you want it to have. If it was intentional, then you need to handle it further down in the program. Maybe you need another if to do something special for this case. If in doubt, you can ask the person that intentionally set it to null what they wanted to achieve.
simply the variable/function you are trying to access from the class does not exist
someClass.xyz();
above will give the error
NoSuchMethod: the method 'xyz' was called on null
because the class someClass does not exist
The following will work fine
// SomeClass created
// SomeClass has a function xyz
class SomeClass {
SomeClass();
void xyz() {
print('xyz');
}
}
void main() {
// create an instance of the class
final someClass = SomeClass();
// access the xyz function
someClass.xyz();
}
I have some code and when I run it produces an error, saying:
NoSuchMethod: the method 'XYZ' was called on null
What does that mean and how do I fix it?
Why do I get this error?
Example
As a real world comparison, what just happened is this conversation:
Hey, how much gas is left in the tank of the car?
What are you talking about, we don't have a car.
That is exactly what is happening in your program. You wanted to call a function like _car.getGasLevel(); but there is no car, the variable _car is null.
Obviously, in your program it might not be a car. It could be a list or a string or anything else really.
Technical explanation
You are trying to use a variable that is null. Either you have explicitly set it to null, or you just never set it at all, the default value is null.
Like any variable, it can be passed into other functions. The place where you get the error might not be the source. You will have to follow the leads from the actual null value to where it originally came from, to find what the problem is and what the solution might be.
null can have different meanings: variables not set to another value will be null, but sometimes null values are used by programmers intentionally to signal that there is no value. Databases have nullable fields, JSON has missing values. Missing information may indeed be the information itself. The variable bool userWantsPizzaForDinner; for example might be used for true when the user said yes, false when the user declined and it might still be null when the user has not yet picked something. That's not a mistake, it's intentionally used and needs to be handled accordingly.
How do I fix it?
Find it
Use the stack trace that came with the error message to find out exactly which line the error was on. Then set a breakpoint on that line. When the program hits the breakpoint, inspect all the values of the variables. One of them is null, find out which one.
Fix it
Once you know which variable it is, find out how it ended up being null. Where did it come from? Was the value never set in the first place? Was the value another variable? How did that variable got it's value. It's like a line of breadcrumbs you can follow until you arrive at a point where you find that some variable was never set, or maybe you arrive at a point where you find that a variable was intentionally set to null. If it was unintentional, just fix it. Set it to the value you want it to have. If it was intentional, then you need to handle it further down in the program. Maybe you need another if to do something special for this case. If in doubt, you can ask the person that intentionally set it to null what they wanted to achieve.
simply the variable/function you are trying to access from the class does not exist
someClass.xyz();
above will give the error
NoSuchMethod: the method 'xyz' was called on null
because the class someClass does not exist
The following will work fine
// SomeClass created
// SomeClass has a function xyz
class SomeClass {
SomeClass();
void xyz() {
print('xyz');
}
}
void main() {
// create an instance of the class
final someClass = SomeClass();
// access the xyz function
someClass.xyz();
}
Here is a little background:
I am trying to test some functions. I CANNOT change anything in the function or any class variables.
So I am calling this function in my unit test, the problem is that, there is a boolean flag, this method simply will just not execute if this flag is not set to true. But this flag has a private setter, so I can directly set it.
I asked around someone told me to use a extension IN the test file to set the variable, but I've tried I don't think I can set it if the extension is not in the same file as the function. Am I doing something wrong? Or is there any other way to test it?
What they were referring to is to place an extension in the file with the class-under-test. So if you have something like:
class ToBeTested {
private(set) var bool: Bool
}
You can add an internal setter:
extension ToBeTested {
func setBoolTrue() { bool = true }
}
But this has to be in the same file with ToBeTested. If you cannot modify that file, this is not a solvable problem. If it needs to be tested this way, then the class will need to be designed to permit that.
When a property is marked private(set), the compiler can assume that the value cannot be changed in any way outside this file. That allows it to apply optimizations that may not be valid if the property were changeable outside this file. The "setter method" may not even exist if the compiler determines that it doesn't need it. For example, it may completely inline that operation, or eliminate it entirely if it can prove the value is never changed.
If obj not exist obj? generate a nil so obj?.attr too.
If obj is nil then obj!.attr crashes.
But if I am sure obj at that certain point of the code always exist, than for me it seems it is independent which one to use. Am I right? What coding styles do you use?
In my very own opinion, if you're really sure that obj exists, you can use ! or ? either. They produce the same effect on an existing object. The only issue is the compiler: sometimes it's fine to use ! instead of ?, sometimes not.
Anyway, if you want to read further on this, give a chance to the free book by Apple "The Swift Programming Language": these things are very well explained there!
If obj exists, obj?.attr returns an optional type even if attr is not an optional. On the other hand, obj!.attr will be whatever type attr is, so no additional unwrapping is needed if attr is a non-optional.
Consider this example:
class Person {
var age = 37
}
var fred: Person? = Person()
let ageNextYear = fred?.age + 1 // error: value of optional type Int? not unwrapped
let ageLastYear = fred!.age - 1 // this works
You use ? when you create a variable with out giving it a value, meaning it can exist and be used in an unitialized state. And as long as it is not initialized it has no type associated to it.
It has nothing do with the value being nil or not.
As Swift is type safe it requires all variables and constant to always hold a value by default, meaning they have a type. So defining something with ? or ! puts a wrapper around it.
enum Optional {
case None
case Some(T)
}
As you see it either has a type or not. Being nil (if possible for a type) or not has not much to do with it. But everything that does not have a type associated is usually nil.
When you then deal with the value of a variable that was declared as being optional, you need to unwrap it by using ! or else you would use the enumeration showed above.
Unwrapping means that you can assert that it does hold a value meaning it has a type. It takes it out of the enumeration and presents the value it has as a type.
Regarding coding style you usually only need to declare something as ? when you work with C or Objective-C APIs. In pure Swift you will usually not declare something as being optional.
You might need to use ! even in pure swift when something might not be defined. For example you have multi-dimensional array that were initialized as being empty. This is because of how Swift currently handle true multi-dimensional objects where the higher dimensions are implicit optionals.
TL;DR: Don't use ? at all unless you are forced to when dealing with C/Obj-C APIs. When using a value of a variable declared with ? always use ! to refer to the value and never ?.
Some links that explains what happens in more detail:
http://www.drewag.me/posts/what-is-an-optional-in-swift
http://www.drewag.me/posts/uses-for-implicitly-unwrapped-optionals-in-swift