Compare id object and NSString - objective-c

I cannot save the selected item from the array with a string value. Any idea what's wrong?
Its my code of compare:
if(self.detailItem){
[WebView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:[self.detailItem description] ofType:#"html"]isDirectory:NO]]];
NSString *value = (NSString *)self.detailItem;
NSString *value1 = (NSString *)#"DecideVectorVPiramidi";
value=[NSString stringWithFormat:#"%#", value];
value1=[NSString stringWithFormat:#"%#", value1];
if (value == value1) {
WebView.scalesPageToFit=YES;
}
This is the array code:
case 1:
switch (self.nomberInSection) {
case 0:
self.detailViewController.detailItem =[NSString stringWithFormat:#"%#", [DecideOfZakusPath objectAtIndex:indexPath.row]];
break;
}
break;
Type of detailItem is id.
For errors, I checked

You need to use isEqualToString. The ==operator will compare by reference only.
This means you have to do
if ( [value isEqualToString:value1] )
{
...
Your two strings will be pointers to two different memory locations, and the == will compare those two memory locations, and consequently evaluate to NO. The isEqualToString, or isEqual, is the method to use for doing a string comparison using the string equality rules (ie. if the two strings contains the same characters, they are considered equal).
This can be a bit counter-intuitive. In Objective-C, operator overloading is not possible. In many other languages, the operators can be overloaded so that a value comparison for built in and custom classes can be done using the equality operator.

Related

Comparing the values of two nsstrings

So I have been trying to compare two NSStrings in xcode. However, it is not working. What am I doing wrong?
NSString Prog are characters that are xml parsed from mysql
char *cStr = "YES";
NSString *str3 = [NSString stringWithUTF8String:cStr];
if ([str3 isEqualToString:prog]) {
[switch1 setOn:YES animated:YES];
}
else {
[switch1 setOn:NO animated:YES];
}
-[NSString isEqualToString:] is normally what you would use, and what you are using in such a scenario. Ensure that prog is a valid NSString (e.g. the correct type and not nil), and keep in mind that string comparison in this implementation is case-sensitive -- i.e. "Yes" would not be equal to "YES".
use the following methods to compare two NSStrings :
[yourString isEqualToString:#"testString"]

Call a method on every word in NSString

I would like to loop through an NSString and call a custom function on every word that has certain criterion (For example, "has 2 'L's"). I was wondering what the best way of approaching that was. Should I use Find/Replace patterns? Blocks?
-(NSString *)convert:(NSString *)wordToConvert{
/// This I have already written
Return finalWord;
}
-(NSString *) method:(NSString *) sentenceContainingWords{
// match every word that meets the criteria (for example the 2Ls) and replace it with what convert: does.
}
To enumerate the words in a string, you should use -[NSString enumerateSubstringsInRange:options:usingBlock:] with NSStringEnumerationByWords and NSStringEnumerationLocalized. All of the other methods listed use a means of identifying words which may not be locale-appropriate or correspond to the system definition. For example, two words separated by a comma but not whitespace (e.g. "foo,bar") would not be treated as separate words by any of the other answers, but they are in Cocoa text views.
[aString enumerateSubstringsInRange:NSMakeRange(0, [aString length])
options:NSStringEnumerationByWords | NSStringEnumerationLocalized
usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop){
if ([substring rangeOfString:#"ll" options:NSCaseInsensitiveSearch].location != NSNotFound)
/* do whatever */;
}];
As documented for -enumerateSubstringsInRange:options:usingBlock:, if you call it on a mutable string, you can safely mutate the string being enumerated within the enclosingRange. So, if you want to replace the matching words, you can with something like [aString replaceCharactersInRange:substringRange withString:replacementString].
The two ways I know of looping an array that will work for you are as follows:
NSArray *words = [sentence componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
for (NSString *word in words)
{
NSString *transformedWord = [obj method:word];
}
and
NSArray *words = [sentence componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
[words enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id word, NSUInteger idx, BOOL *stop){
NSString *transformedWord = [obj method:word];
}];
The other method, –makeObjectsPerformSelector:withObject:, won't work for you. It expects to be able to call [word method:obj] which is backwards from what you expect.
If you could write your criteria with regular expressions, then you could probably do a regular expression matching to fetch these words and then pass them to your convert: method.
You could also do a split of string into an array of words using componentsSeparatedByString: or componentsSeparatedByCharactersInSet:, then go over the words in the array and detect if they fit your criteria somehow. If they fit, then pass them to convert:.
Hope this helps.
As of iOS 12/macOS 10.14 the recommended way to do this is with the Natural Language framework.
For example:
import NaturalLanguage
let myString = "..."
let tokeniser = NLTokenizer(unit: .word)
tokeniser.string = myString
tokeniser.enumerateTokens(in: myString.startIndex..<myString.endIndex) { wordRange, attributes in
performActionOnWord(myString[wordRange])
return true // or return false to stop enumeration
}
Using NLTokenizer also has the benefit of allowing you to optionally specify the language of the string beforehand:
tokeniser.setLanguage(.hebrew)
I would recommend using a while loop to go through the string like this.
NSRange spaceRange = [sentenceContainingWords rangeOfString:#" "];
NSRange previousRange = (NSRange){0,0};
do {
NSString *wordString;
wordString = [sentenceContainingWord substringWithRange:(NSRange){previousRange.location+1,(spaceRange.location-1)-(previousRange.location+1)}];
//use the +1's to not include the spaces in the strings
[self convert:wordString];
previousRange = spaceRange;
spaceRange = [sentenceContainingWords rangeOfString:#" "];
} while(spaceRange.location != NSNotFound);
This code would probably need to be rewritten because its pretty rough, but you should get the idea.
Edit: Just saw Jacob Gorban's post, you should definitely do it like that.

Converting NSNumber to NSString is not realy a string

I have got a problem with converting an NSNumber value to an NSString
MyPowerOnOrNot is an NSNumber witch can only return a 1 or 0
and myString is an NSString..
myString = [NSString stringWithFormat:#"%d", [myPowerOnOrNot stringValue]];
NSLog(#"%#",myString);
if(myString == #"1") {
[tablearrayPOWERSTATUS addObject:[NSString stringWithFormat:#"%#",#"ON"]];
}
else if(myString == #"0") {
[tablearrayPOWERSTATUS addObject:[NSString stringWithFormat:#"%#",#"OFF"]];
}
What is wrong with this?
The NSLog shows 0 or 1 in the console as a string but I can't check it if it is 1 or 0 in an if statement?
If doesn't jump into the statements when it actually should.. I really don't understand why this doesn't works..
Any help would be very nice!
A couple of problems
myString = [NSString stringWithFormat:#"%d", [myPowerOnOrNot stringValue]];
-stringValue sent to an NSNumber gives you a reference to a string. The format specifier %d is for the C int type. What would happen in this case is that myString would contain the address of the NSString returned by [myPowerOnOrNot stringValue]. Or, on 64 bit, it would return half of that address. You could actually use [myPowerOnOrNot stringValue] directly and avoid the relatively expensive -stringWithFormat:
if(myString == #"1")
myString and #"1" are not necessarily the same object. Your condition only checks that the references are identical. In general with Objective-C you should use -isEqual: for equality of objects, but as we know these are strings, you can use -isEqualToString:
if ([[myPowerOnOrNot stringValue] isEqualToString: #"1"])
Or even better, do a numeric comparison of your NSNumber converted to an int.
if ([myPowerOnOrNot intValue] == 1)
Finally if myPowerOnOrNot is not supposed to have any value other than 0 or 1, consider having a catchall else that asserts or throws an exception just in case myPowerOnOrNot accidentally gets set wrong by a bug.
"myString " is a reference to a string, not the value of the string itself.
The == operator will compare the reference to your string literal and so never return true.
Instead use
if( [myString isEqualToString:#"1"] )
This will compare the value of myString to "1"
In Objective C; you can't compare strings for equality using the == operator.
What you want to do here is as follows:
[tablearrayPOWERSTATUS addObject:([myPowerOnOrNot integerValue]?#"ON":#"OFF"])];
Compact, fast, delicious.

Does core data do its own type casting in the background?

I am working on a simple comparison of two lists to see which items in an "evaluation" list are contained in a larger "target" list. I am getting the data on-the-fly- by parsing two CSV files and storing everything as strings. I successfully import the data into the data store and I can get a list of entities no problem
The problem comes when I actually do a search. Essentially, I am looking for short ISBNs in the form of 1234 from the evaluation list in the target list, which are in the form of 1234-5. The predicate I am using is I am using the CONTAINS comparison in the form of [NSString stringWithFormat:#"%# CONTAINS %#", kOC_Target_PrintBookCode, evalIsbn]
The error I get is the following (grabbed by my NSLog)
NSInvalidArgumentException: Can't look for value (1494) in string (49885); value is not a string
I get the impression that even though the ISBN is being read from a NSString and the Core Data store has the data point spec'd as a String, that Core Data is still doing something in the background with the value for whatever reason it sees fit. Any ideas?
Here is the relevant process logic (though I use that term dubiously) code. Unless otherwise noted in the code, all values being manipulated and/or stored are NSString:
NSArray *evalBooks = [self getEntitiesByName:kOC_EntityName_EvalBook
usingPredicateValue:[NSString stringWithFormat:#"%# > \"\"", kOC_Eval_Bookcode]
withSubstitutionVariables:nil
inModel:[self managedObjectModel]
andContext:[self managedObjectContext]
sortByAttribute:nil];
if ( ( !evalBooks ) || ( [evalBooks count] == 0 ) ) {
// we have problem
NSLog(#"( !evalBooks ) || ( [evalBooks count] == 0 )");
return;
}
[evalBooks retain];
int firstEvalBook = 0;
int thisEvalBook = firstEvalBook;
int lastEvalBook = [evalBooks count]; NSLog(#"lastEvalBook: %i", lastEvalBook);
for (thisEvalBook = firstEvalBook; thisEvalBook < lastEvalBook; thisEvalBook++) {
NSManagedObject *evalBook = [[evalBooks objectAtIndex:thisEvalBook] retain];
NSString *rawIsbn = [[evalBook valueForKey:kOC_Eval_Bookcode] retain];
NSString *isbnRoot = [[self getIsbnRootFromIsbn:rawIsbn] retain];
// this is a custom method I created and use elsewhere without any issues.
NSArray *foundBooks = [self getEntitiesByName:kOC_EntityName_TargetBook
usingPredicateValue:[NSString stringWithFormat:#"%# CONTAINS %#", kOC_Target_PrintBookCode, isbnRoot]
withSubstitutionVariables:nil
inModel:[self managedObjectModel]
andContext:[self managedObjectContext]
sortByAttribute:kOC_Target_PrintBookCode];
if ( foundBooks != nil ) {
[foundBooks retain];
NSLog(#"foundBooks: %lu", [foundBooks count]);
} else {
}
If you're building your predicate as an NSString, I believe
[NSString stringWithFormat:#"%# CONTAINS %#", kOC_Target_PrintBookCode, isbnRoot]
should actually be
[NSString stringWithFormat:#"%# CONTAINS '%#'", kOC_Target_PrintBookCode, isbnRoot]
It seems that you're confusing the way predicateWithFormat: works with the way stringWithFormat: works.
Presumably either kOC_Target_PrintBookCode or isbnRoot is not an object that can be converted to a string. E.g. if either is an integer, the %# operator cannot convert the integer to a string value.

Objective-C switch defines contents of string

I've come from a java background, so i'm still getting to grips with some of the ways of doing things with Obj-C.
Depending on a number provided, I want an NSString variable to have different contents.
In java I would do something like this:
string foo;
switch (numberToSwtich){
case 1:
foo = "Something!";
break;
case 2:
foo = "Something Else!";
break;
}
Obviously there are two types of String in objective-c. NSString and NSSMutableString.
The difference being that you can change one at a later date. However, like java, can I initialize a NSString first then set its contents later or do I need to use an NSMutableString?
Something a bit like this...
NSString *aString = [[NSString alloc] init];
switch ([self getNumberOfSides]) {
case 1:
aString = #"A String";
break;
case 2:
aString = #"Another String";
break;
}
I'm aware there are other-ways of doing this, such as using an NSDictionary with numeric keys for example, but I would like to use a switch.
Thanks.
Your code is perfectly valid. There's no need to use NSMutableString.
Your code does leak memory, because you're not releasing the empty string you allocated using alloc. It's better to use the "string" class method for empty strings:
NSString *aString;
switch ([self getNumberOfSides]) {
case 1:
aString = #"A String";
break;
case 2:
aString = #"Another String";
break;
default:
aString = [NSString string];
break;
}