Property access results unused but NSLog works fine - ios

I'm trying to display results in a text label, but I get different result than NSLog:
if( [elementName isEqualToString:#"CommunityID"])
{
self.recordResults = FALSE;
ResultLabel.text = #"CommunityID: %#", self.soapResults;
NSLog(#"CommunityID:%#",self.soapResults);
self.soapResults = nil;
}
NSlog correctly shows the text result, but the UILabel doesn't. The error shows:
"Property access result unused - getters should not be used for side effects"
I don't understand how NSlog gets the info just fine but the other doesn't? Any ideas?

You can't assign directly, You need to do with stringWithFormat property
ResultLabel.text = [NSString stringWithFormat:#"CommunityID: %#", self.soapResults];

Just so you know what was happening and what the compiler warning was about…
In C and Objective-C, a comma (,) that's not separating arguments in a function or method call is the comma operator. It is a compound expression. The left-hand sub-expression is evaluated but its result is discarded. Then, the right-hand sub-expression is evaluated and the overall compound expression takes its value.
In your case, the compound expression was just used as a statement and its result was not used. So, your statement:
ResultLabel.text = #"CommunityID: %#", self.soapResults;
was the equivalent of:
ResultLabel.text = #"CommunityID: %#";
self.soapResults;
The second of those statements calls a property getter and discards the resulting value. The compiler is warning you. Either you didn't mean to do that (as in this case) or you were invoking the getter because the getter has side effects that you wanted, which is a really bad idea.

Related

How can I convert a string in a textfield to an Int in Swift?

I tried for a long time to turn the text into an Int but it did not work. I tried it like this:
(AnzahlString is a textfield)
var AnzahlAInt = 0
if let AnzahlAString = AnzahlString.text {
let AnzahlAInt = Int(AnzahlAString)
}
But then I always get the error:
Value of optional type 'Int?' must be unwrapped to a value of type 'Int'
Then I added a ! at the end of Int(AnzahlAString)! so I don't get a error, but now when I press on the button, the app crashes. It was predictable, but how can I change this now to an Int without the !?
At first glance, it looks like you have two things to check for:
is AnzahlString.text present, and
does it represent an Int
The first check is in fact not necessary, since .text will never return nil, even though it's marked as Optional. This means you can safely force-unwrap it.
The second check is easily done by using the ?? operator:
let AnzahlAInt = Int(AnzahlString.text!) ?? 0
PS, just as a stylistic hint: variable names in Swift ususally start with a lowercase letter, names starting with capital letters are used for types.
PPS: your code as written shadows AnzahlAInt - the value of your var is never changed.
The reason why the resulting Int is optional, is that parsing might or might not succeed. For example, if you try to parse the string "Fluffy Bunnies" into an Int, there is no reasonable Int that can be returned, therefore the result of parsing that string will be nil.
Furthermore, if you force the parser by using !, you're telling Swift that you know for sure that the string you pass will always result in a valid Int, and when it doesn't, the app crashes.
You need to handle the situation in which the parse result is nil. For example:
if let AnzahlAIntResult = Int(AnzahlAString) {
// We only get here if the parse was successful and we have an Int.
// AnzahlAIntResult is now an Int, so it can be assigned to AnzahlAInt.
AnzahlAInt = AnzahlAIntResult
}
You did a good job so far but missed out one thing.
This line tries to convert the String into an Int. However this can fail, since your String can be something like this "dfhuse".
let AnzahlAInt = Int(AnzahlAString)
This is why the result of Int(AnzahlAString) is an Optional (Int?). To use it as an real Int, you have to unwrap it.
First solution is the !, however, every time this does fail your app crashes. Not a good Idea to use so.
The best solution would be Optional Binding, as you already used to get the text of your text field.
if let AnzahlAString = AnzahlString.text {
if let safeInt = Int(AnzahlAString) {
// You can use safeInt as a real Int
} else {
print("Converting your String to an Int failed badly!")
}
}
Hope this helps you. Feel free to ask again if something is unclear.
For unwrapping you can also use guard like this
Simple and easy
guard let AnzahlAInt = Int(AnzahlString.text!) else {
return
}
print(AnzahlAInt)

How to check if object is nil? [duplicate]

I am currently studying objective-c and the basic c programming language.
I have a questions about a particular line of code:
if (!balance)
Balance is an object that is created. I understand that this code is checking to see if the object balance is nil or not, is this correct?
Could somebody please explain how exactly the code checks for nil? Does it return 0 if the value of balance is nonzero and 1 if the value is 0?
Thanks in advance.
In Objective-C, nil is roughly analogous to 0, NULL or false, but for object pointers. In an if statement, it will behave the same as one of the aforementioned scalar values. For example, the following two if statements should produce the same results:
NSNumber *balance = nil;
if (!balance) {
// do something if balance is nil
}
if (balance == nil) {
// do something if balance is nil
}
NSLog should return (null) (which probably is description for nil), not NULL in console. Your check should look like this:
if (!controller)
{
// do some stuff here
}
If balance is nil then it will be a pointer to 0x0. That address is never used for a valid object.
In C anything within an if that evaluates to zero is considered a negative response, anything that evaluates to non-zero is a positive response.
Pointers evaluate to their address — exactly as if you cast them to an integral type. The ! means "NOT".
So the test is if(address of balance is not zero).
First you need to understand how if works. Basically, any non-zero value is treated as true and a zero value is treated as false.
Something as simple as if (10) will be treated as true while if (0) is treated as false.
Any expression evaluates to either a value of zero or a non-zero value.
An object pointer is just a number - a memory address. A nil pointer is simply an address of 0. Any non-nil pointer will have a non-zero address.
The ! operator negates that state. A non-zero value will be treated as a zero value and visa-versa.
So now combine all of this.
Foo *bar = nil;
if (bar) // false since bar is nil (or zero)
Foo *bar = [[Foo alloc] init]; // some non-nil value
if (bar) // true since bar is non-zero
Foo *bar = nil;
if (!bar) // true since !bar mean "not bar" which is "not zero" which is "non-zero"
Foo *bar = [[Foo alloc] init]; // some non-nil value
if (!bar) // false since !bar mean "not bar" which is "not non-zero" which is "zero"

I have an if statement nested in a for-in loop that evaluates incorrectly

I'm using a for-in loop to get each object out of a dictionary of objects (passingObservations) and placing certain ones in an array of objects. It checks for a specific NSString #Property of the object and see if it is equal to another NSString. When equal, it places the object into schoolMArray. The if statement evaluates TRUE for the first run through the for-in loop and adds the object to the schoolMArray. On successive loops through the for-in, it evaluates FALSE. It shouldn't be doing that though. I've put in exact copies of the same object and it still evaluates the second object as FALSE.
for (NSString *key in keysArray) {
ObservationData *obj = [self.passingObservations objectForKey:key];
if (obj.districtName == self.passingDistrict) {
[schoolMArray addObject:obj];
}
}
What have I done wrong here?
You compared objects for equivalence using == rather than isEqual: (or, in the specific case of strings, isEqualToString:).

Method To Delete 2nd Label, Then First Label, Not Functioning Correctly

I know I am missing something obvious, but I just cannot see it. This method is meant to compare the text of a label to the text of a text box, and then delete the text. So if the 1st label reads "Puppy" and the 2nd label reads "Kittens," and the text box says "Kittens," the method should delete the text of the 2nd label and leave the 1st label's text. If the 2nd label is blank, then the method should delete the text of the 1st label.
But no matter how I mess with the method, either it deletes the 2nd label but not the 1st, deletes both of them, or deletes neither of them. Here's what I've tried
(lblFabric1 is the 1st label, lblFabric2 is the 2nd label, txtType is the text box):
-(IBAction)btnDelete:(id)sender
{
if ((self.lblFabric2.text== self.txtType.text))
{
self.lblFabric2.text = #"";
}
else if ((self.lblFabric2.text != self.txtType.text))
{
self.lblFabric1.text=#"";
}
}
It deletes the 2nd label, but not the 1st label. If I try to set the "Else if" to:
else if ((self.lblFabric2.text==#""))
it gives me an error (""Direct comparison of a string literal has undefined behavior.") Am I just going about this the wrong way? What am I missing?
You should not use == or != for string comparison in Objective C. You need to use the isEqualToString or isEqual method.
if (([self.lblFabric2.text isEqualToString:self.txtType.text]))
When you use == or != you are comparing the pointers where the strings are stored.
To compare NSStrings use:
if ([myString1 isEqualToString:myString2])
Documentation
Compairing String literals using == is not guaranteed to behave as you might expect. Use isEqual: or isEqualToString: instead.
See http://nshipster.com/equality/.
When you are comparing NSStrings with == what you are actually comparing are two memory addresses and that is not what you are really intended for. You want to compare the values of two strings what == operator is not suitable for and thus you are getting the warning
Direct comparison of a string literal has undefined behavior.
To compare the values of NSStrings you should use isEqualToString: method. You could have also use isEqual: method derived from NSObject class but that is not suitable for Unicode comparison. So isEqualToString: is always the safest bet.
After using isEqualToString: your code should look something like:
-(IBAction)btnDelete:(id)sender
{
if ([self.lblFabric2.text isEqualToString:self.txtType.text])
{
self.lblFabric2.text = #"";
}
else
{
self.lblFabric1.text=#"";
}
}

iOS giving incompatible pointer types assignment error

I am using below code, it gives the error:
incompatible pointer types assignment to 'NSString *'
to the parament of the 'NSString *'" where dataParameter is used.
Here is the code:
- (id)initWithText:(NSString *)someText passedData:(animalsViewController *)dataParameter
{
NSLog(dataParameter);
self.title=dataParameter;
nowCountry=dataParameter;
return self;
}
How can I fix this?
You're treating "dataParameter", which is an instance of "animalsViewController" as an NSString. That doesn't work, you can only assign objects of the same type to each other.
NSLog is expecting a string parameter. Use the formatting arguments to convert dataParameter to an NSString:
NSLog(#"%#", dataParameter);
For your other two assignments, it seems unlikely that you want to assign a viewController object to a property like title that is an NSString. It's more likely that you want to assign an NSString property of dataParameter, something like this:
self.title = dataParameter.title;
or:
nowCountry = dataParameter.country;
Since I don't know what properties an AnimalsViewController has, I'm just guessing a property names, but that should illustrate the point.

Resources