iOS NSComparisonresult issue - objective-c

It raises an exception when I enter more than two characters in the searchfield. I use NSComparisonResult to show results on a UITableView:
- (void)filterContentForSearchText:(NSString*)searchText
{
for (mystring in self.array)
{
NSComparisonResult result = [mystring compare:searchText options:(NSCaseInsensitiveSearch)
range:NSMakeRange(0, [searchText length])];
if (result == NSOrderedSame)
{
NSUInteger index=[self.array indexOfObjectIdenticalTo:mystring];
NSUInteger maxindex = index + 50;
for (index ; (index < [self.array count] && index <= maxindex && index!= NSNotFound); index ++)
{
[self.filteredListContent addObject:[NSDictionary dictionaryWithObjectsAndKeys:[self.array objectAtIndex:index],#"english",[self.secondarray objectAtIndex:index],#"translated",nil]];
}
break;
}
}
The output shows:
-[UIDeviceWhiteColor compare:options:range:]: unrecognized selector sent to instance 0x5e4a5d0
2011-11-06 12:10:51.932 XXX[2583:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIDeviceWhiteColor compare:options:range:]: unrecognized selector sent to instance 0x5e4a5d0'
What does UIDeviceWhiteColor in this case mean?
self.array = [[NSArray alloc] initWithArray:
[[NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"first" ofType:#"txt"]
encoding:NSUTF8StringEncoding error:NULL] componentsSeparatedByString:#"\n"]];
self.secondarray = [[NSArray alloc] initWithArray:
[[NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"second" ofType:#"txt"]
encoding:NSUTF8StringEncoding error:NULL] componentsSeparatedByString:#"\n"]];

That's because there is a UIDeviceWhiteColor somewhere in your self.array, which should be made of just NSStrings. How do you populate this array?

There's a UIDeviceWhiteColor object in self.array. You should also cast mystring as an NSString or whatever kind of object it is. If you'd cast it in UIDeviceWhiteColor then the compiler would give you a warning that UIDeviceWhiteColor does not respond to compare:options:range:.
for (NSString *mystring in self.array)
{
//some code
}

Related

Code runs in a Cocoa application, but fails in a command line tool

The error is a EXC_BAD_ACCESS, which is typically a bad pointer of some sort, but the problematic _rawText property is created in the same scope where it fails. Here's the code from the command line tool. The only difference between this and the app version is the URL for the file, and via NSLog I've verified that both files are being read and have the same length, as they should.
Here's the updated code, which sometimes runs and sometimes fails. I'm using getters and setters for rawText this time around, instead of accessing _rawText directly.
-(void)loadDictionary {
NSURL *cedict_url = [NSURL fileURLWithPath:#"cedict_ts.txt"];
NSLog(#"cedict_url is %#", cedict_url);
NSError *loadError;
[self setRawText:[NSString stringWithContentsOfURL:cedict_url encoding:NSUTF8StringEncoding error:&loadError]];
// _rawText = [NSString stringWithContentsOfURL:cedict_url encoding:NSUTF8StringEncoding error:&loadError];
if (_rawText == nil) NSLog(#"No _rawText object");
if (loadError == nil) NSLog(#"No error from stringWithContentsOfURL:");
if (loadError) {
NSLog(#"%#", loadError);
return;
} else {
// This next line fails with the error "Thread 1: EXC_BAD_ACCESS (code=1, address=0x20)
NSLog(#"Dictionary loaded, string of length %lu", (unsigned long)[[self rawText] length]);
// 0x20 is kind of small for an NSString's memory location
}
NSArray *rawLines = [[self rawText] componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
NSLog(#"Broke file into %lu lines", (unsigned long)[rawLines count]);
NSLog(#"First 10 lines are...");
for (int iLine = 0; iLine < 10; iLine++) {
NSString *theLine = [rawLines objectAtIndex:iLine];
NSLog(#"Line %d, %lu characters: %#", iLine, theLine.length, theLine);
}
NSMutableArray *singleHanCharacterLines = [NSMutableArray arrayWithCapacity:[rawLines count]];
for (NSInteger i=0; i<[rawLines count]; i++) {
NSString *line = [rawLines objectAtIndex:i];
NSComparisonResult hasHash = [line compare:#"#" options:NSCaseInsensitiveSearch range:NSMakeRange(0, 1)];
NSComparisonResult isSpace = [line compare:#" " options:NSCaseInsensitiveSearch range:NSMakeRange(1, 1)];
BOOL nonComment = hasHash != NSOrderedSame;
BOOL oneHanLine = isSpace == NSOrderedSame;
if (nonComment & oneHanLine) [singleHanCharacterLines addObject:line];
}
NSLog(#"Found %lu lines starting with a single Han character", (long int)[singleHanCharacterLines count]);
dLines = [NSArray arrayWithArray:singleHanCharacterLines];
}
The NSLog that prints the length of _rawText gives the same result for both versions.
Are there some settings that I need to change, or some additional techniques I've forgotten? Thanks!

Adding objects from array to dictionary

I am getting rows from a SQLite DB and trying to insert them into a dictionary. Except I keep getting errors! I get the error "Implicit conversion of an Objective-C pointer to 'const id *' is disallowed with ARC" Which I know means that I cant use a pointer when I am adding objects to my dictionary. So how do I go about fixing it so I can add those arrays to a dictionary?
NSArray *keyArray = [[NSMutableArray alloc] init ];
NSArray *valueArray = [[NSMutableArray alloc ] init ];
NSDictionary* dic;
NSInteger dataCount = sqlite3_data_count(statement);
while (sqlite3_step(statement) == SQLITE_ROW) {
#try {
for (int i = 0; i < dataCount; i ++)
{
NSString* key = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, i)];
NSString *value = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, i)];
if ([value length] == 0)
{
value = #"";
}
keyArray = [keyArray arrayByAddingObject:key];
valueArray = [valueArray arrayByAddingObject:value];
}
}
#catch (NSException *ex)
{
NSLog(#"%#,%#", [ex name], [ex reason]);
}
dic= [NSDictionary dictionaryWithObjects:valueArray forKeys:keyArray count:[keyArray count]];
The dictionaryWithObjects:forKeys:count: takes C-style arrays, not NSArray objects. The dictionaryWithObjects:forKeys: may do the trick, but you may be better off constructing a mutable dictionary as you go, bypassing NSArrays entirely.
NSDictionary* dic;
NSMutableDictionary *tmp = [NSMutableDictionary dictionary];
for (int i = 0; i < dataCount; i ++)
{
NSString* key = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, i)];
NSString *value = [NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, i)];
[tmp setObject:value forKey:key];
}
dict = tmp;
[dicBodyPost setValue:arrContactAddress forKey:#"contactAddress"];

NSArray elements from parsed .xml file not accessible on iPhone, using TouchXML

I have an NSMutableArray *myArray, wich is the result of a properly .xml parsed file, using TouchXML.
I just want to extract all elements with key name and store then in a separate NSMutableArray, but my final NSMutableArray *namesList is not accessible, crashing my iPhone app right away, because it only contains the last enumerated string and not the whole array.
Here is the code:
NSMutableArray *namesList = [[NSMutableArray alloc] initWithArray:myArray copyItems:YES];
int i;
for (i = 0; i < [myArray count]; i++)
{
namesList = [[myArray objectAtIndex:i] objectForKey:#"name"];
NSLog(#"All Names: %#", namesList);
}
NSLog(#"First Name: %#", [namesList objectAtIndex:0]); <-- crashing line
And here is the NSLog:
-[__NSCFString objectAtIndex:]: unrecognized selector sent to instance 0x6a42540
2012-04-04 10:34:07.882 Sections[3610:f803] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString objectAtIndex:]: unrecognized selector sent to instance 0x6a42540'
You should be able to do this:
NSMutableArray * namesList = [NSMutableArray alloc] init];
for(i = 0; i < [myArray count]; i++)
{
NSString * tempString = [NSString stringWithString:[[myArray objectAtIndex:i] objectForKey:#"name"]];
[namesList addobject:tempString];
}
NSLog(#"First Name: %#", [namesList objectAtIndex:0]);
[[myArray objectAtIndex:i] objectForKey:#"name"]; returns an NSString object and not another array therefore you can't send an objectAtIndex to it. Check the structure of your arrays.

NSString.length gives EXC_BAD_ACCESS

I have the following code:
NSArray *array = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:nil];
NSString *temp;
for (int i = 0; i < [array count]; i++)
{
temp = [array objectAtIndex:i];
NSLog(#"temp length = %#", [temp length]);
}
I get an EXC_BAD_ACCESS error at the NSLog line. I assume it's erring out at the [temp length] bit. The weird thing is, I can do other methods of NSString on temp and they work fine, like [temp characterAtIndex:0].
I've also tried doing [[array objectAtIndex:i] retain];, but that doesn't seem to help.
Does anyone know why I'm getting this error?
EDIT: Turns out it was crashing at the NSLog because it was %# instead of %lu. The real problem was with other code that I had omitted from this post. After playing around with it some more, I got it working.
From my understanding, the "%#" placeholder is for object pointers, "length" returns "NSUInteger" which is not a pointer. Try "%lu" instead of "%#".
This (slightly cleaned up) version works for me:
NSError *error = nil;
NSString *path = [#"~/Desktop" stringByExpandingTildeInPath];
NSArray *array = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:
path error:&error];
if (error) NSLog(#"%#", error);
for (NSString *path in array) {
NSLog(#"Path length = %lu", path.length);
}
As thg435 mentioned, "%#" is for object pointers, so if you pass it an arbitrary number it will throw a memory access error.

potential leak problems

when I build and analize my application , am getting potential leak near the code [array1 release]...why its happening there..?thanks in advance
- (void) touchOnFeaturedCatalog
{
searchId == 2;
//featuredCatalogName = #"23064_Leeds2010";
//NSString *response = [ZoomCatalogAppDelegate getResponseFromServer:[NSString stringWithFormat:#"http://www.zoomcatalog.com/iphone/iphone.php?catalog=%#&iphone=Yes&pdf=No", featuredCatalogName]];
NSString *response = [ZoomCatalogAppDelegate getResponseFromServer:#"http://www.zoomcatalog.com/iphone/supplier.php"];
//NSString *response = [ZoomCatalogAppDelegate getResponseFromServer:#"http://test.atvescape.com/articles.php"];
//NSLog(#"Response = %#", response);
NSArray *array = [response componentsSeparatedByString:#"##"];
[array retain];
for(int i = 0; i < array.count; i++)
{
NSLog(#"Trying outer loop.... %d, %#, %#", i, [array objectAtIndex:i], featuredCatalogName);
NSArray *array4 = [featuredCatalogName componentsSeparatedByString:[array objectAtIndex:i]];
if(array4.count > 1)
{
response = [ZoomCatalogAppDelegate getResponseFromServer:[NSString stringWithFormat:#"http://www.zoomcatalog.com/iphone/catalog_search.php?tid2=%#&iphone=yes", [array objectAtIndex:i]]];
NSArray *array3= [response componentsSeparatedByString:#"<br>"];
//baseURL = [NSString stringWithFormat:#"%#", [array3 objectAtIndex:0]];
global_ContentString = [NSString stringWithFormat:#"%#", [array3 objectAtIndex:2]];//(searchId == 1 ? [array objectAtIndex:2] : ([array objectAtIndex: isLineNameSearch ? 2 : 1]))];
[global_ContentString retain];
// NSLog(#"baseURL = %#", global_ContentString);
NSArray *array1 = [global_ContentString componentsSeparatedByString:#"###"];
for(int j = 0; j < array1.count; j++)
{
NSArray *array2 = [[array1 objectAtIndex:j] componentsSeparatedByString:#"##"];
NSString *str = [NSString stringWithFormat:#"%#", [array2 objectAtIndex:0]];
str = [str stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if ([str caseInsensitiveCompare:featuredCatalogName] == NSOrderedSame)
{
global_ContentString = [ZoomCatalogAppDelegate getResponseFromServer:[NSString stringWithFormat:#"http://www.zoomcatalog.com/iphone/iphone.php?catalog=%#&iphone=Yes&pdf=No", [array2 objectAtIndex:5]]];
baseURL = [NSString stringWithFormat:#"%#", [[global_ContentString componentsSeparatedByString:#"<br>"] objectAtIndex:0]];
//global_ContentString = [NSString stringWithFormat:#"%#", [[global_ContentString componentsSeparatedByString:#"<br>"] objectAtIndex:1]];
[global_ContentString retain];
[global_MainPageController presentModalViewController:global_FullPageController animated:YES];
//NSLog(#"$$$$$$$$$$$$$$$$$$$$$$ Catalog id = %# $$$$$$$$$$$$$$$$$$$$$$$$$$", [array2 objectAtIndex:5]);
//[array1 release];memory leak
return;
}
// NSLog(#"Trying inner loop.... %d, %#, %#", j, str, featuredCatalogName);
}
}
// if([[array objectAtIndex:i] com
}
[array release];
return;
}
sorry for all..
If you are only using an object locally (within the method in which it is created) you can autorelease it. Objects that are created or returned by convenience methods available until the end of the function call. Unless you need the objects elsewhere, I suggest ditching the retain calls. The rule of thumb is that whenever you call alloc, new, retain, or copy you mist release the object. However, if you use a convenience method, The returned object is autogenerate for you.
It seems that you call [global_ContentString retain]; but then fail to call a corresponding release.