-[NSCFString objectAtIndex:]: unrecognized selector - iphone

I have this little problem I couldn't find in Google:
UITableView works fine until I start scrolling.
Error Message: `-[NSCFString objectAtIndex:]: unrecognized selector sent to instance 0x5f24870 `
Method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:MyIdentifier] autorelease];
}
// Set up the cell
int storyIndex = [indexPath indexAtPosition: [indexPath length]-1];
//populate cell
cell.textLabel.text = [[myArray objectAtIndex: storyIndex] objectForKey: #"subject"];
return cell;
}
Just guessed that was the "problem"-method... if you need more infos: please tell me :)
thanks for all your help!
EDIT:
myArray is just the normal NSArray *myArray
It's a sorted Array ->
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"lesson" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
myArray = [resultArray sortedArrayUsingDescriptors:sortDescriptors];
resultArray (NSMutableArray) is the Result of an XML-Parser.. hope you can see my problem..

It means that you're sending an objectAtIndex: messages to an object of type NSString (or possibly CFString). Of course you're expecting myArray to be an array and not a string.
What probably happened is that your array is being released (almost certainly autoreleased) too early and that by the time the method above is called the memory that was being pointed at by myArray now holds a string.
In response to your edit...
This line:
myArray = [resultArray sortedArrayUsingDescriptors:sortDescriptors];
...is incorrect. The value is autoreleased. You need to retain it:
myArray = [[resultArray sortedArrayUsingDescriptors:sortDescriptors] retain];
Remember to release it before you close the view!

myArray is proberbly autoreleased. Use self.myArray to set the sorted array. (with the correct #property (retain) )

If you have correctly identified this method as the culprit I'm guessing this line is the problem:
cell.textLabel.text = [[myArray objectAtIndex: storyIndex] objectForKey: #"subject"];
To me it looks lime myArray is an instance of NSCFString and not a NSArray. You should start by double checking that and that you never assign anything but NSArray instances to myArray.
--edit--
Try
self.myArray = [resultArray sortedArrayUsingDescriptors:sortDescriptors];
That should correctly retain the array for yoy to make sure it is not garbage collected and replaced with a rouge string :)

If myArray is an instance variable instead of a property, try:
myArray = [[resultArray sortedArrayUsingDescriptors:sortDescriptors] retain];

Related

Issue in adding dynamic cell in table view?

Please have a look on my code which i am using to add dynamic cells in my table view add run time. At did select of my table view i have called this method.
- (void) allServersFound
{
// called from delegate when bonjourservices has listings of machines:
NSArray *newPosts = [[NSArray alloc]initWithObjects:#"A", nil]; // NSArray of machine names;
NSMutableArray *tempArray = [[NSMutableArray alloc] initWithObjects: #"A",#"B",#"C",#"D", nil];
int i = 0;
for (NSArray *count in newPosts)
{
[tempArray addObject:[NSIndexPath indexPathForRow:i++ inSection:0]];
}
[[self tblHome] beginUpdates];
[[self tblHome] insertRowsAtIndexPaths:tempArray withRowAnimation:UITableViewRowAnimationNone];
[[self tblHome] endUpdates];
[tempArray release];
}
But this give me following Exception at run time:
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSIndexPath _fastCStringContents:]: unrecognized selector sent to instance 0x4e0e130
First you initialize your tempArray with strings like this:
NSMutableArray *tempArray = [[NSMutableArray alloc] initWithObjects: #"A",#"B",#"C",#"D", nil];
Then you add indexPaths like this:
[tempArray addObject:[NSIndexPath indexPathForRow:i++ inSection:0]];
so the array you pass to the insertRowsAtIndexPaths method contains both strings and indexPaths objects. I think this is the reason of the exception.
As others noted, your tempArray contains a mixture of NSString and NSIndexPath objects. This is the most obvious thing that you need to address before you do anything else. You can use [NSMutableArray array] class method for that (it's autoreleased, so you'll need to remove the call to [tempArray release] at the end of your method).
A less obvious thing is that the model of your UITableView must be updated before you call insertRowsAtIndexPaths, otherwise you would get another exception in a much less obvious place.
Your tmparray contains NSString values as well as the IndexPaths, try removing the NSStrings first.
Try replacing the line
NSMutableArray *tempArray = [[NSMutableArray alloc] initWithObjects: #"A",#"B",#"C",#"D", nil];
with the line
NSMutableArray *tempArray = [[NSMutableArray alloc] initWithObjects:nil];

how pass array value on other class for display data in iphone

Hi friends thank for helping to me
I have doubt when i pass one array value for display on other controller class in tableView so I get nil value on that controller how to take array value on that class of other controller for display purpose
my lstAirports is a array which created on Airport.h and my Airport.h is simple class is not delegate the code of this class:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
loginStatus = [[NSString alloc] initWithBytes: [webData mutableBytes] length:[webData length] encoding:NSUTF8StringEncoding];
[connection release];
NSString *regexString = #"Stations\\[""(.*)""\\] = new Station\\((.*)new Array\\((.*)\\)\\);";
matchArray = [loginStatus arrayOfCaptureComponentsMatchedByRegex:regexString];
//NSLog(#"matchArray: %#", matchArray);
lstAirports = [[NSMutableArray alloc] initWithCapacity:[matchArray count]];
for (int i = 0; i < [matchArray count]; i++) {
airport *air=[[airport alloc]init];
//code
NSString *temp=[[matchArray objectAtIndex: i] objectAtIndex: 1];
NSString *newString=[temp stringByReplacingOccurrencesOfString:#"\"" withString:#""];
arrParts=[newString componentsSeparatedByString:#","];
air.Code =[arrParts objectAtIndex:0];
//air.Code = [[matchArray objectAtIndex: i] objectAtIndex: 1];
NSLog(#"air.Code: %#\n",air.Code);
//name
temp=[[matchArray objectAtIndex: i] objectAtIndex: 2];
newString=[temp stringByReplacingOccurrencesOfString:#"\"" withString:#""];
arrParts=[newString componentsSeparatedByString:#","];
air.Name=[arrParts objectAtIndex:2];
NSLog(#"air.Name: %#\n",air.Name);
//destination airports
temp=[[matchArray objectAtIndex: i] objectAtIndex: 3];
newString=[temp stringByReplacingOccurrencesOfString:#"\"" withString:#""];
arrParts=[newString componentsSeparatedByString:#","];
air.DestinationAirports =arrParts;
NSLog(#"air.DestinationAirports: %#\n",air.DestinationAirports);
[lstAirports addObject: air];
NSLog(#"lstAirports: %#\n",lstAirports);
//NSString *str=
//[air release];
}
}
- (void)dealloc {
[super dealloc];
[loginStatus release];
//[lstAirports release];
[webData release];
// [window release];
}
When I pass this array on my `Odselectioncontroller.m` then I get nil value of array where I am wrong friends please help me out this is my controller class code
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return obj.lstAirports.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
airport *a=(airport*)[obj.lstAirports objectAtIndex:indexPath.row];
NSLog(#"str:%#",a);
cell.textLabel.text =a.Name;
and `Airport` is other class where i am create name property for fetch value name from array in yhis class
You are always creating new instance of your Airports class obj which will return you nil value always.
If you want to pass a array from one to other then you can do it by two ways-
make your array global by using extern keyword.
you can define a array in second class as a property and then can set it.
for more you can refer this -
Passing data between classes using Objective-C
DO one thing declare the NSMutable Array in AppDelegate and synthesize the array and using this array to store objects in any class and use this array to display in any class directly by using appDelegate.ArrayName Hope it helps You :)
Here you can do like,
Airport.h class as Sigleton and use .
Otherwise
Declare a Array in APPDelegate and access it in you needed class by sharedObject mechanism
Either you can pass the array using an array object which is synthesized in the class. Another option is to have a method(which takes a NSArray object as parameter) in the class you want to populate and call the method on your first class passing the array as parameter.
Your code also requires a slight change in the dealloc method. Its advised not to call [super dealloc]; before releasing the objects of the class. Always call [super dealloc]; at the end after releasing all objects.

iphone : proplem with table view

I have a problem with table view in iphone .. i can't figure out why it crashes everytime
will here is the code
- (void)viewDidLoad
{
[self checkAndCreatePList];
NSMutableDictionary* plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:pListPath];
self.animals = [plistDict objectForKey:#"Animals"];
[super viewDidLoad];
}
-(UITableViewCell *) tableView:(UITableView *) tableView cellForRowAtIndexPath:(NSIndexPath *) indexPath
{
static NSString *SimpleTableIdentifier =#"SimpleTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SimpleTableIdentifier];
if(cell== nil){
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:SimpleTableIdentifier]autorelease];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [animals objectAtIndex:row];
return cell;
}
it's crashes at the line
cell.textLabel.text = [animals objectAtIndex:row];
and tells me that
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary objectAtIndex:]: unrecognized selector sent to instance
The Animals key in your plist refers to a dictionary, not an array. Dictionaries don't have a guaranteed order, so asking for an object at a particular index doesn't make sense.
In addition to this, you have a memory leak - plistDict is allocated but never released. Have you run the static analyser over your code?
[plistDict objectForKey:#"Animals"];
is returning a Dictionary not an Array like you are expecting. You need to check out your plist file to see if the data is correct.
the error seems that you are calling objectAtIndex on a NSDictionary object at line cell.textLabel.text = [animals objectAtIndex:row]; check what does animal contains at run time. For this use NSLog before this line. NSLog(#"%#",animals);
Looks like animals is some dictionary and you are calling objectAtIndex: method on it. objectAtIndex: is NSArray method.

Help w/ array of dictionaries in a tableview

This is kinda confusing so please bear with me.
I have an array (listOfStates) of dictionaries. Where listOfStates has this structure:
{stateName} - {stateCapital}
{Alabama} - {Montgomery}
{Alaska} - {Juneau}
{Arizona} - {Phoenix}
...
{West Virginia} - {Charleston}
{Wisconsin} - {Madison}
{Wyoming} - {Cheyenne}
This is the code used to obtain the 1st letter of each US State(stateName) in order to group them together alphabetically:
listOfStates = [[NSArray alloc] init];
stateIndex = [[NSMutableArray alloc] init];
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
for (NSDictionary *row in listOfStates) {
[tempArray addObject:[row valueForKey:#"stateName"]];
for (int i=0; i<[tempArray count]-1; i++){
char alphabet = [[tempArray objectAtIndex:i] characterAtIndex:0];
NSString *uniChar = [NSString stringWithFormat:#"%C", alphabet];
if (![stateIndex containsObject:uniChar]){
[stateIndex addObject:uniChar];
}
}
}
That code works beautifully, however I'm having issues understanding how to populate a tableview cell with BOTH the #"stateName" and #"stateCapital"(as the subtitle) after I use NSPredicate to sort the array.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
//---get the letter in the current section---
NSString *alphabet = [stateIndex objectAtIndex:[indexPath section]];
//---get all states beginning with the letter---
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF beginswith[c] %#", alphabet];
NSArray *states = [[listOfStates valueForKey:#"stateName"] filteredArrayUsingPredicate:predicate];
//---extract the relevant state from the states object---
cell.textLabel.text = [states objectAtIndex:indexPath.row];
//cell.textLabel.text = [[listOfStates objectAtIndex:indexPath.row] objectForKey:#"stateName"];
//cell.detailTextLabel.text = [[listOfStates objectAtIndex:indexPath.row] objectForKey:#"stateCapital"];
return cell;
}
Any help is appreciated and I am more than willing to send the entire project, if you think it'll help you understand.
Thank you so much.
cell.textLabel.text = [[states objectAtIndex:indexPath.row] objectForKey:#"stateName"];
cell.detailTextLabel.text =[states objectAtIndex:indexPath.row] objectForKey:#"stateCapital"];
Update:
Unfortunately, the 'states' array only
includes the state names...
Change the predicate and filter to:
NSPredicate *p=[NSPredicate predicateWithFormat:#"stateName beginswith[c] %#", alphabet];
NSArray *states=[listOfStates filteredArrayUsingPredicate:p];
...that will give you an array of states that all start with the same letter. Then you can sort the array and the row will give you the right state dictionary.
Maybe change the data structure so you have one dictionary with state name as a key and state capital as a value. That way you can sort your keys and get the value using the keys, not indexes.

UITableView not reloading section and contents

I have a refresh button in the toolbar that regenerates an NSArray and attempts to reload the contents of the table.
However, whether I have:
if (boolCondition) {
[self refreshTableDataSet];
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:kTableSectionOfInterest] withRowAnimation:UITableViewRowAnimationFade];
}
or:
if (boolCondition) {
[self refreshTableDataSet];
[self.tableView reloadData];
}
About every other attempt to refresh the table fails. Sometimes it works, sometimes not.
I have some NSLog statements in -tableView:cellForRowAtIndexPath: to let me know when this method is being fired. When the refresh fails, I do not see the output of these NSLog statements.
Is there something I'm missing about reloading a table view, when I have new data?
EDIT
In my -refreshTableDataSet method:
- (void) refreshTableDataSet {
NSSortDescriptor *_objectTypeSorter = [[[NSSortDescriptor alloc] initWithKey:#"object.type" ascending:YES] autorelease];
NSSet *_objectSet = [managedObjectContext fetchObjectsForEntityName:#"Object" withPredicate:[NSPredicate predicateWithFormat:[NSString stringWithFormat:#"group.name like '%#'", [group name]]]];
self.objects = [[[_objectSet allObjects] sortedArrayUsingDescriptors:[NSArray arrayWithObjects: _objectTypeSorter, nil]] retain];
}
In my table view -tableView:cellForRowAtIndexPath: method:
...
Object *_object = [self.objects objectAtIndex:indexPath.row];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = _object.name;
cell.detailTextLabel.text = _object.type;
cell.imageView.image = [UIImage imageNamed:#"GroupType.png"];
cell.accessoryView = [self imageViewForObjectDetailType:_object.type];
...
I have a method for the accessoryView called -imageViewForObjectDetailType, which just returns a UIImageView:
return [[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"GenericObjectDetailType.png"]] autorelease];
Are there retain and/or release messages that I am missing?
I'm sure you've checked this, but I see random behavior like this if I have an NSArray that wasn't retained and passed on to a tableview.
Looking at your added code, I don't see anything wrong at first glance - here are some tips:
1.In:
self.objects = [[[_objectSet allObjects] sortedArrayUsingDescriptors:[NSArray arrayWithObjects: _objectTypeSorter, nil]] retain];
If objects is a #property with retain attribute, then you don't need to retain it here again. Not why it would fail though.
2.In your cellForRowAtIndexPath:, you do have something like:
UITableViewCell *cell = (UITableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
just before the if (cell == nil), right?
3.You might want to NSLog the value of object when you get it from the array in
Object *_object = [self.objects objectAtIndex:indexPath.row];
4.Break this up onto multiple lines and look at all the return values with NSLog to make sure they all succeed every time you refresh.
self.objects = [[[_objectSet allObjects] sortedArrayUsingDescriptors:[NSArray arrayWithObjects: _objectTypeSorter, nil]] retain];
5.Double check this to make sure your fetch is getting you what you expect:
NSSet *_objectSet = [managedObjectContext fetchObjectsForEntityName:#"Object" withPredicate:[NSPredicate predicateWithFormat:[NSString stringWithFormat:#"group.name like '%#'", [group name]]]];
You can NSLog the [_objectSet count] to watch to see whether an unsuccessful refresh gives you a bad count.
Hope this helps.