iOS Compare Value of Label - ios

I'm using a label to display the string result of function. However I have a class variable that stores the previous result and I need to update that variable in different ways depending on different conditions. The code I wrote is
if(displayPassword.text == #"Memorable")
{
prevpass = [newPassword returnPassword];
}
else
{
prevpass = displayPassword.text;
}
However it always jumps to the else as it seems to show under debugging that displayPassword.text is always empty depsite it showing a value.

You can only use == to compare scalar values. A string is an object. You need to use the isEqual: or isEqualToString: method instead.
if([displayPassword.text isEqualToString:#"Memorable"]) {

Related

Checking if array is nil or not [duplicate]

This question already has answers here:
Check if optional array is empty
(8 answers)
Closed 4 years ago.
I have a array of my custom model, and I want to check if it is not nil and its size is greater then 0.
Following is my array with custom object
var listCountries : [Countries]? = nil
now In viewDIdLoad I want to make a check on it. I am new to Swift. I have good experience in working in Java.
I have read out Optional values concept and guard, if let statements. But I am unable to understand how efficiently they may be used. I have read too much SO questions but failed to figure out.
for example , if I want to check the upper given array in java I have only to do
if(listCountries != null && listCountries.size()>0){
//DO something
}
So to summarize my question:
How to make the upper given(Java code) check in to swift 4.? What is more smooth and reliable way.
What is a use of if let , guard, guard let statements. if I declare a variable (array, string) as optional I have to bear optional check like force wrapping each and every place. This is for me so making too much confusion.
Please help. I know this question has been asked in different ways. But this has some different context.
Just use ??.
if !(listCountries ?? []).isEmpty {
However, since you want to probably use listCountries in the if block, you should unwrap
if let listCountries = self.listCountries, !listCountries.isEmpty {
Ideally, if nil and empty means the same to you, don't even use an optional:
var listCountries: [Countries] = []
I would do it something like...
if let list = listCountries, !list.isEmpty { // Can also use list.count > 0
// do something
}
Even though you are not using the list inside the braces you are still using the list in the condition.
Or, like Sulthan said... make it non-optional to begin with if it makes no difference.
Obviously, I would assume that you are able to recognize the difference between nil array and empty array.
So, if we tried to implement a literal translation to your question:
I want to check if it is not nil and its size is greater then 0
For the first condition:
// "I want to check if it is not nil":
if let unwrappedList = listCountries {
// ...
}
and for the second condition:
// "I want to check if it is not nil":
if let unwrappedList = listCountries {
// "and its size is greater then 0":
if !unwrappedList.isEmpty {
// ...
}
}
However, you could combine both of the conditions by using the comma to achieve the multi-clause condition:
// I want to check if it is not nil and its size is greater then 0
if let unwrappedList = listCountries, !unwrappedList.isEmpty {
// ...
}
Or by using guard statement:
// I want to check if it is not nil and its size is greater then 0
guard let unwrappedList = listCountries, !unwrappedList.isEmpty else {
return
}
if let list = listCountries {
if(!list.isEmpty && list.count > 0) {
//value
}
}

how do you return nil if a certain type is passed to a function in Swift?

ok so I am trying to return nil if a certain type is passed into my function. In this case im passing in an instance of my class "BlogPost" and a type within this blogpost. I also have an array called "types" and I have assigned the variable Videos to the last index of that array. If this type is passed into my function I would like to return nil (so assuming im going to need an optional here for returning a possible nil) this is what I have so far :-
so all in all I need to pass in an instance of my blog post but always return nil if a certain type is passed in. Hope this makes sense
Update:
The types array is defined as follows:
let types : [String] = ["technology", "Fashion", "Animals"]
this is the array I am referring to in the function. Basically if that last entry of the array is entered into the function I need to return nil
sure this is blogpost it does actually have an empty string for type
great so im getting there what Ive done now is change the blogpost.type to choose one at random. So now if the specfic type is chosen from this array how would I do that still getting an error. This is what I have updated to
so now all I need to do is access the 2 type in that array and if I do access it return nil. Any thoughts on that? so to drag it on thanks
I don't think you can. You can create failable initialisers which does what you need but you cannot use it with normal function.
The best solution for you would be return optional Int or String and when you call the function just check the result for nil and do what you need to do, otherwise ignore it:
func randomViews(blog : BlogPost.Type) -> Int? {
case 10:
return nil
case 10, 20 :
return 0
default:
random
}
if (randomViews(parameter) == nil) {
//function returned nil
}
You have displayed error because you compare optional blog to Videos, you have to unwrap it first, for example if you are sure the blog has always have a value use:
if blog! == Videos
if not sure is safer to use:
if let blg = blog {
if blg == Videos {
}
else {
// blog has not have a value
}
You are passing blog as a BlogPost.Type parameter. That is not correct. You should have either just passed it the String parameter, or you could pass it the BlogPost itself:
func randomViews(blog: BlogPost) {
let videos = types[2]
if blog.type == videos {
// do whatever you want
}
// carry on
}
Unrelated to your question at hand, but notice that I use let instead of var when defining videos. Always use let if the value will not (and cannot) change.
Also note that I use lowercase letter v in videos, because Cocoa naming conventions dictate that variables generally start with lowercase letters, whereas types, classes, structs, and enums generally start with uppercase letters.

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=#"";
}
}

cannot insert into NSMutableArray due to indexvalue being out of bounds

I have a MutableArray on this view called array and the object in question is detailItem, which has a property of rank (int). On this view, there's a text field displaying the rank and I want to be able to move the detailItem up and down the MutableArray by changing the rank.
So, for example let's say the detailItem has a rank of 3, which is index value of 2. If I change this in the text field to 3, I want the array to adjust and move it down one place. However, as I type in the value of rankField (the text field), it crashes the app since it automatically updates the value before I'm done editing. So, if I click on the text field and write 23 (planing on deleting the 2) or just press delete (now the value is nil) the app crashes with an uncaught exception.
Here's the code:
- (IBAction)rankFIeldTextChanged:(id)sender {
QueueMember *member = self.detailItem;
[self.array removeObjectAtIndex:self.detailItem.rank];
if (0<= [self.rankField.text intValue]<= self.array.count) {
[self.array insertObject:member atIndex:[self.rankField.text intValue]-1];
}
}
The if condition of making the text value in-between the array size and 0 seems to have no effect.
btw this is all in the detailsViewController which is connected to the main view controller via push segue. does it make more sense(or more better coding) to just set the new rank value in details and actually make the array changes in the mainviewcontroller.m?
The problem is that you are trying to do two boolean statements at once (which doesn't work). Change your if statement to something like:
if (0< [self.rankField.text intValue] && [self.rankField.text intValue] < self.array.count) {
//Insert your object here
}
else
{
//Add object here
}
Your current setup check to see if 0<= [self.rankField.text intValue], which will return true for all values greater than or equal to 0. Then it checks the result of that (YES:1, NO:0) if it's less than or equal to your array count. That will always return true if your array has anything in it. So basically your check will always return true.
Since it always returns true I could check for array object number 1000, your if statement says go for it, then I check and the array says "No way in heck!" and crashes your app.
EDIT: Updated my code snippet to take into account your array insertion line.
I'd just do this
- (IBAction)rankFIeldTextChanged:(id)sender {
QueueMember *member = self.detailItem;
[self.array removeObjectAtIndex:self.detailItem.rank];
if ((0<= [self.rankField.text intValue])&&([self.rankField.text intValue]<= self.array.count)) {
if (self.array.count >([self.rankField.text intValue]-1)){
[self.array insertObject:member atIndex:[self.rankField.text intValue]-1];
}
}
}
you are probably trying to insert at an index greater than the count of the array.

Objective C - differentiate between nil and 'no value'

im building a chart view and I'm giving it a datasource to which it can ask for a Y value that corresponds to a given X index. In some cases, there is no Y value for a given X index. I can't send nil in this circumstance, as 0 may be a perfectly valid Y value. What is the best way in objective C to communicate that there is No Value at all?
It seems to me that you're sending the data between the model and the view using some sort of object, perhaps NSNumber, that's holding a value, and you are retrieving the value by sending it a message, and you know that if the object is nil, the message send will return 0.
That's correct. In this case, simply check if the object is nil, and proceed accordingly:
- (void)plotValue:(NSNumber *)number
{
if (number == nil) {
// no value
} else {
// Value may be 0, but you can now safely plot it.
}
}
Don't use primitives in your data source, instead use NSNumber. Then you can differentiate between nil and an NSNumber storing the value 0.
nil is not 0. They are different.
If you are using NSNumber, then nil is clearly disjoint from the set of NSNumber.
If you are using int, then you can't use nil.
If you don't want to use an object (NSNumber), you can return a negative number (if possible) or the maximum/minimum integer that is unlikely to be returned by the datasource.
I'm assuming you're talking about some scalar like an NSInteger or something. If literally any integer is valid for the Y value, then there is no way to do this. However, most likely there is some practical range, so you can just choose some value outside this range to be "special". For example, Cocoa has the value NSNotFound, which NSArray will return if you ask for the index of an object that is not in the array. It is defined as the largest possible NSInteger. You could reuse this yourself if your Y value will never be NSIntegerMax.
The other option, assuming you don't want to create a special type just for this, would be to have your method return both Y and whether or not Y was actually found. For example, some rough pseudocode:
- (NSInteger)yForX:(NSInteger)x wasFound:(BOOL *)found {
if (yWasFound) {
if (found)
*found = YES;
return y;
} else {
if (found)
*found = NO;
return 0;
}
}
You could use NSNumber, as some have suggested, but I find it a little awkward to deal in NSNumbers just to get nil.

Resources