How to convert NSMutableArray Object's NSString data into lowercase in iOS? - objective-c

I am working with sqlite database.
I retrieve text data from sqlite database into NSMutableArray named myArray.
In that myArray variable, there is a column named "info" with text data.
After i retrieve that data into NSMutableArray , i would like to convert all of text data from sqlite database into lowercase.
I wrote following code in searchBar's textDidChange Event like that.
NSInteger counter = 0;
for(NSString *nameMe in myArray)
{
NSRange r = [[nameMe lowercaseString] rangeOfString:[searchText lowercaseString]];
if(r.location != NSNotFound)
{
if(r.location== 0)
{
[tableData addObject:nameMe];
}
}
counter++;
}
However there is a error occurring in lowercaseString.
This error is
2012-03-31 16:28:18.217 SqliteTest[1812:f803] -[MyInfoClass lowercaseString]: unrecognized selector sent to instance 0x6da9210
2012-03-31 16:28:18.276 SqliteTest[1812:f803] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[MyInfoClass lowercaseString]: unrecognized selector sent to instance 0x6da9210'
I think that compiler doesn't know how to convert object data into lowercase.
How can i solve that?
Can i convert object (NSString) data into lowercase.
If it can be,Please let me know how to do that.
Thanks you for your helping.

I think that compiler doesn't know how to convert object data into lowercase.
The problem is that objects of type MyInfoClass don't have a method -lowercaseString. You're iterating over the array assuming that every object in the array is a NSString, but that's apparently not true -- there's definitely at least one instance of MyInfoClass in myArray. So, one way to fix the problem is to make sure that you only add strings to the array.
Here's a shorter, safer way to do what you're doing above:
NSArray *lowercaseArray = [myArray valueForKey:#"lowercaseString"];
NSArray's -valueForKey: will send a -valueForKey: message with the key you provide to every object in the array, and collect the results in an array. Even better, if some object in the array returns nil, the resulting array will contain a NSNull object at that index. You'll want to check for those NSNull's when you use the array, but you won't get an exception like you do in your code.
Update: From the OP's comment, it seems that the reason for converting the array to lowercase is to make case insensitive searching possible. It's worth pointing out that there are better ways to accomplish that. Here are two:
Use NSString's -caseInsensitiveCompare: method to compare strings, if you're doing the comparison yourself.
If you're using a predicate to search for a match, use string comparison operators (LIKE, CONTAINS, etc.) with the case-insensitive option: #"SELF like[c] %#". You may also want the diacritic-insensitive option: #"SELF like[cd] %#".

Related

Putting NSData into an NSArray

I have NSData objects storing data (non character / non-ascii). I'm trying to put it into an array without it being interpreted as characters or ascii. I know this question has been asked a few times before, but none of the solutions posted have worked for me in this situation. I'm trying to avoid using property lists, which is what most answers suggested. I already tried converting the NSData to an NSString, then storing the string in the array, but of course it is interpreted as characters after putting it in the string, regardless of the encoding I've used. For example, one of the NSData's contains the value 2c, and when I put it into a string it is interpreted as ,. Does anyone know how I can store the raw data, in its original state, in an NSArray? Maybe by storing the data in user defaults, then somehow storing the defaults in an array? I'm at a loss.
Here is some possibly relevant code:
NSData *receivedData = [bleDevice readData];
NSString *receivedDataString = [[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding];
[dataArray insertObject:receivedDataString atIndex:0];
When I call:
[dataArray insertObject:receivedDataString atIndex:0];
It will store something like 2c ad a ,.
But, when I try and insert the raw data, like:
[dataArray insertObject:receivedData atIndex:0];
It will simply not store anything. There are no warnings, no errors. I'll NSLog the array and it is null.
[dataArray insertObject:receivedData atIndex:0]; most certainly will insert "receivedData" into "dataArray" (so long as both exist). "receivedData" can be any sort of NSObject -- need not be a string. If the array is "null" when you log it then the array itself never got created.
(It's important to remember that if an object pointer is nil then method calls on that pointer do not fail but rather silently return zero/nil, so "returns nil" strongly suggests the object never was created.)

Why can't I add nil objects to NSMutableArrays?

I have a situation where I'd like to be able to maintain an array of pointers that might all possibly point to nil.
Equipment *equipment[19];
However, I've found that I cannot set an array of pointers, or a double-pointer, as a property of an object.
My workaround when I can't use C-style arrays is to use the NSArray objects. So I attempted to do something like the following:
NSMutableArray *equipment = [NSMutableArray arrayWithCapacity: NUM_EQUIPSLOTS];
for (int i=0; i<NUM_EQUIPSLOTS; i++) {
[equipment setObject: nil atIndexedSubscript: i];
}
The idea here being I have an array of empty pointers that will later point to stuff.
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
*** First throw call stack:
(0x246e012 0x1e4be7e 0x2421b6a 0x2421a20 0xebd02 0xde82b 0xc9d5a 0xcb6bd 0x4d525 0xc94fa 0xc8b6a 0xa18157 0xa18747 0xa1994b 0xa2acb5 0xa2bbeb 0xa1d698 0x3176df9 0x3176ad0 0x23e3bf5 0x23e3962 0x2414bb6 0x2413f44 0x2413e1b 0xa1917a 0xa1affc 0xc8526 0x1fa5)
libc++abi.dylib: terminate called throwing an exception
I know I can do this very easily using C-style arrays, and with individual objects. I'd rather do it this way than something dumb like:
Equipment *equipment0 = nil;
Equipment *equipment1 = nil;
Equipment *equipment2 = nil;
// ...
Equipment *equipment18 = nil;
This probably has to do with the structure of the NSArray model itself. Would someone explain to me why this is, and why I can't simply add or set nil objects in NSArray? Thank you in advance.
The "why" is both trivial and unsatisfying. It is because NSMutableArray holds objects, and nil is not an object. ObjC has a strong distinction between objects and primitive types. nil is a primitive type. As CodaFi notes, you can use NSNull or NSPointerArray to address these. The typical solution is NSNull.
There is no good reason. NSArray and NSMutableArray stores pointers to objects. nil is a decent pointer to an object. The Java equivalent is ArrayList, which does permit null elements. It was just a design choice.
One possible historical reason for this design choice is that the most common way to create an array and fill it with elements is to use the -initWithObjects:... or +arrayWithObjects:... methods, which use varargs to take as many arguments as the user wants to give and put it in the array. Since with varargs in C, it is impossible to determine the number of arguments, the way they chose to indicate how many was to use nil as a "terminator" to signal the end of the list. (There are other ways to indicate the number, e.g. pass the number as the first argument.) The disadvantage of this method was that you cannot put nil as one of the "arguments" that you wanted to put in the array, since it would terminate the list.
However, those methods were not the only ways to create an array and fill it with elements. You could create an empty array and add each one separately, or you could use the -initWithObjects:count: or +arrayWithObjects:count: methods, which are not varargs and thus did not have the nil terminator issue. Now, there is also the array literal syntax (which calls -initWithObjects:count: internally) which makes it even easier. It is perfectly conceivable to have NSArray and NSMutableArray that allows nil elements; just that you cannot use -initWithObjects:... or +arrayWithObjects:... to add the nil elements. However, they chose not to do this.

can I sort NSMutable array of NSStrings by their substrings using the selector (in place)?

I have a NSMutableArray consisting out of NSStrings. When I need to sort it, I use [array sortUsingSelector:#selector(caseInsensitiveCompare:)] which works perfect.
But sometimes I need to sort the array by substrings of NSStrings. The substring is defined in this case as part of NSString following some marker. The thing is complicated further by the fact that marker can be positioned differently in every string.
Obviously I can break NSString into 2 objects and do sorting on them but it will require significant changes.
Is there a way to do the sorting using selector similar to what I have described above?
I think if not, then I might sort by creating a sorted copy of an array (instead of using selector to do it in place), then releasing the original.
You can perform any arbitrarily complex sorting inline with NSMutableArray's sortWithOptions:usingComparator:
[myMutableArray sortWithOptions:NSSortStable usingComparator:^NSComparisonResult(NSString* str1, NSString* str2) {
// Scan for your marker in both strings and split on it...
// Say you store the results in substr1 and substr2...
return [substr1 caseInsensitiveCompare:substr2];
}];

What characters does a new empty NSString contain?

i created an NSMutableString with the method stringWithCapacity:5
How do i test if characterAtIndex:0 is empty
Empty string contains no characters, even if you created it with non-zero capacity. To check if string is empty simply check its length:
if ([myString length] == 0){
// empty
}
Moreover, trying to access a character at index which is >= of string's length will result in NSRangeException exception.
The *WithCapacity methods that we see on NSString, NSArray, etc, have nothing to do with pre-populating the contents of the object. They are simply a means by which you can suggest to the object how much it's going to hold. If you suggest a large enough number, it may use a different storage mechanism than if it were a small number.
So in other words, you could do [NSMutableString stringWithCapacity:1234567890] and it give you exactly the same thing as if you had simply done [NSMutableString string], and the -length of the resulting object will always be 0.
Frankly, the *WithCapacity methods are pretty useless. I've never found a reason to use them.

Objective-C for Dummies: How do I get a value out of NSDictionary?

so I'm having the most difficult of time pulling values out of an NSDictionary. Right now I just have a dictionary that is populated from a JSON call and it only contains a key named 'Success' with a value of 0 or 1.
How do I do a conditional on that value to check if its 0 or 1? I've tried a bunch of things, but I'm not getting anywhere. Here's my current code:
[[jsonDictionary objectForKey:#"Success"] isEqualToNumber:1]
I'm getting passing argument 1 of 'isEqualToNumber:' makes pointer from integer without a cast' as a warning, and the app crashes when it hits that line anyway.
And a subquestion, what's the difference between objectForKey and valueForKey? Which one should I use by default?
Anyway, this noob in Objective-C would truly appreciate some help on this. Thanks in advance!
Since dictionaries contain Objective-C objects, an entry containing a number is an NSNumber instance. NSNumber provides a convenience method, -intValue, for extracting its underlying int value:
if ([[jsonDictionary objectForKey:#"Success"] intValue] == 1) { … }
Note that NSNumber has other convenience methods for extracting its underlying value as other C data types.
In most cases, you should use -objectForKey: instead of -valueForKey:. The former is the canonical method to obtain an entry in the dictionary and is declared in NSDictionary. The latter is declared in NSObject and is used in Key-Value Coding contexts, where the key must be a valid KVC key, and there’s additional processing — for instance, if you’re using -valueForKey: in a dictionary with a key that starts with #, that character is stripped from the key and [super valueForKey:key] is called.
The number 1 is not an object pointer. Use an NSNumber instance instead if you want to use a number in an NSDictionary.
[[jsonDictionary objectForKey:#"Success"]
isEqualToNumber:[NSNumber numberWithInteger:1]]
[[jsonDictionary objectForKey:#"Success"] isEqualToNumber: [NSNumber numberWithInt:1]]
Number and Value Programming Topics: Using Numbers
NSNumber: What is the point ?
You can get the value of dictionary in different ways like checking
the value first.
Solution 1: Using simple if statement.
int value = 0;
if ([[jsonDictionary objectForKey:#"Success"]intValue]==1){
value = [[jsonDictionary objectForKey:#"Success"]intValue];
}
Solution 2: Using ternary operator
value = ([[jsonDictionary objectForKey:#"Success"]intValue]==1) ? 1:0;