I am developing an iOS App. When I try to get the number of cells for section using a NSMutableArray, I get
[__NSCFString count]: unrecognized selector sent to instance
0x60400043f9c0.
Please help. Here is the code:
for (NSDictionary *dict in _array) {
NSString *dic = [dict objectForKey:#"product_base"];
if (dic == nil) {
}else{
[_productfliters addObject:dic];
}
NSString *dicMaterial = [dict valueForKey:#"product_material"];
if (dicMaterial == nil) {
}else{
[_productfliters addObject:dicMaterial];
}
// NSMutableDictionary *value = [[NSMutableDictionary alloc]init];
// [value setValue:[dict valueForKey:#"product_size"] forKey:#"ABC"];
NSString *dicSize = [dict valueForKey:#"product_size"];
[_productfliters addObject:dicSize];
}
self.sectionNames =[_arrayHeading mutableCopy];
self.sectionItems =[_productfliters mutableCopy];
NSLog(#"%#",self.sectionItems);
_tableview.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
_tableview.rowHeight = UITableViewAutomaticDimension;
_tableview.estimatedRowHeight = 100;
self.expandedSectionHeaderNumber = -1;
[_tableview reloadData];
- (void)tableViewExpandSection:(NSInteger)section withImage:(UIImageView *)imageView {
NSArray *sectionData = [self.sectionItems objectAtIndex:section];
if (sectionData.count == 0) { //Error this part app crash NSCFString count
self.expandedSectionHeaderNumber = -1;
return;
} else {
[UIView animateWithDuration:0.4 animations:^{
imageView.transform = CGAffineTransformMakeRotation((180.0 * M_PI) / 180.0);
}];
NSMutableArray *arrayOfIndexPaths = [NSMutableArray array];
for (int i=0; i< sectionData.count; i++) {
NSIndexPath *index = [NSIndexPath indexPathForRow:i inSection:section];
[arrayOfIndexPaths addObject:index];
}
self.expandedSectionHeaderNumber = section;
[_tableview beginUpdates];
[_tableview insertRowsAtIndexPaths:arrayOfIndexPaths withRowAnimation: UITableViewRowAnimationFade];
[_tableview endUpdates];
}
}
You unload strings and put them into _productfliters:
for (NSDictionary *dict in _array) {
NSString *dic = [dict objectForKey:#"product_base"];
if (dic == nil) {
}else{
[_productfliters addObject:dic];
}
...
You then assign that to sectionItems:
self.sectionItems =[_productfliters mutableCopy];
You then extract one of those strings, but call it an array (even though you put strings in there, so it's a string):
NSArray *sectionData = [self.sectionItems objectAtIndex:section];
Just because you say NSArray here doesn't make it so. You're just telling the compiler what you expect to be true. objectAtIndex: return id ("any object"). It trusts you when you say it's an NSArray, but it isn't true.
You then call .count on a NSString and crash.
It's unclear what you're actually trying to do here, but you have an array of strings, not an array of arrays.
Note that ObjC has a new feature called lightweight generics that would possibly have caught this mistake. Had you declared sectionNames as either NSArray<NSString *>* or NSArray<NSArray<NSString *>*>* (depending on which one you wanted this to be), the compiler probably would have thrown a warning (maybe even an error). Lightweight generics are nowhere near as powerful as Swift's generics, but they can catch some type mismatches like this.
Related
I thought what I am trying to do is really basic stuffs, I have 2 NSMutableArrays that contains MyItem objects. I want to remove the item from one array and add it to another array but it throws exception when trying to remove it and Yes to save you a complain, my understanding of fundamental OOP is a failure. I am not even dealing with enumerate thru array at all.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
MyItem *item = [self.completedItems objectAtIndex:indexPath.row];
if(![self.toDoItems containsObject: item])
[self.toDoItems addObject: item];
if([self.completedItems containsObject: item])
[self.completedItems removeObject:item];
[self.tableView reloadData]; //reload contents on table view controller
}
Here is the exception
[__NSArrayI removeObject:]: unrecognized selector sent to instance 0x8d8bba0
here is how the arrays are loaded. it is array of dictionaries basically.
#interface ToDoListTableViewController : UITableViewController
#property (strong) NSMutableArray *completedItems;
#property (strong) NSMutableArray *toDoItems;
#end
self.toDoItems = [[NSMutableArray alloc] init]; //initialize array
self.completedItems = [[NSMutableArray alloc] init]; //initialize array
MyItem *newItem = [[MyItem alloc] init];
newItem.text = [item valueForKey:#"text"];
newItem.completed = [[item valueForKey:#"completed"] boolValue];
newItem.date = [item valueForKey:#"date"];
if (newItem.completed) {
[self.completedItems addObject: newItem];
}
else
{
[self.toDoItems addObject: newItem];
}
EDIT
Maybe this code somehow makes the destination arrays to become Immutable ones?
UINavigationController *navigationController = segue.destinationViewController;
CompleteTableViewController *objChild = (CompleteTableViewController *)navigationController.topViewController;
if(objChild != nil){
objChild.completedItems = [self.completedItems copy];
objChild.toDoItems = [self.toDoItems copy];
}
Thanks in advance for point out my issue.
As the exception points out self.completedItems is an NSArray, not an NSMutableArray. NSArray has no such method removeObject.
Update! There's the problem code!
if(objChild != nil){
objChild.completedItems = [self.completedItems copy]; //should be mutableCopy
objChild.toDoItems = [self.toDoItems copy]; //should be mutableCopy
}
Based on the code you were reassigning the data to your property as an immutable object
if(objChild != nil){
objChild.completedItems = [self.completedItems copy];
objChild.toDoItems = [self.toDoItems copy];
}
if you want it to be mutable, you should use:
if(objChild != nil){
objChild.completedItems = [self.completedItems mutableCopy];
objChild.toDoItems = [self.toDoItems mutableCopy];
}
that is why you get exception:
if (objChild != nil) {
// INCORRECT immutable copy, aka NSArray
objChild.completedItems = [self.completedItems copy];
objChild.toDoItems = [self.toDoItems copy];
}
the code above should look like:
if (objChild != nil) {
// CORRECT mutable copy, aka NSMutableArray
objChild.completedItems = [self.completedItems mutableCopy];
objChild.toDoItems = [self.toDoItems mutableCopy];
}
because it happens in runtime the compiler is not able to warn you, therefore you got the crash only.
__NSArrayI removeObject:]: unrecognized selector sent to instance 0x8d8bba0 ,
this tells you that your array is not mutable ArrayI (array immutable), please double-check what you have loaded into property. Nothing stops you from loading NSNumber,NSString,NSArray to be loaded into property where you expect type of NSMutableArray, so then you are ready for a nasty surprise...
I'm trying to parse a JSON file to my iOS app table view.
When I launch the app I see that it parses the data, but when I begin to scroll the app instantly crashes and gives me this error: Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSNull length]: unrecognized selector sent to instance 0x38094a60'
My code:
#import "FirstViewController.h"
#import "YoutubePost.h"
#interface FirstViewController ()
{
NSInteger refreshIndex;
NSArray *title;
NSArray *about;
NSArray *views;
NSArray *rating;
NSArray *votes;
NSArray *content;
}
#end
#implementation FirstViewController
#synthesize tweets;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = NSLocalizedString(#"Videos", #"Videos");
self.tabBarItem.image = [UIImage imageNamed:#"newtab1"];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.myTableView.separatorColor = [UIColor clearColor];
[self issueLoadRequest];
[self setNeedsStatusBarAppearanceUpdate];
}
-(UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleLightContent;
}
#pragma mark - Table view data source
- (void)issueLoadRequest
{
// Dispatch this block asynchronosly. The block gets JSON data from the specified URL and performs the proper selector when done.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData* data = [NSData dataWithContentsOfURL:[NSURL URLWithString:#"my-site.php/file.json"]];
[self performSelectorOnMainThread:#selector(receiveData:) withObject:data waitUntilDone:YES];
});
}
- (void)receiveData:(NSData *)data {
// When we have the data, we serialize it into native cocoa objects. (The outermost element from twitter is
// going to be an array. I JUST KNOW THIS. Reload the tableview once we have the data.
self.tweets = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
[self.myTableView reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.tweets.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"YoutubePost";
YoutubePost *cell = (YoutubePost *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"YoutubePost" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
// The element in the array is going to be a dictionary. I JUST KNOW THIS. The key for the tweet is "text".
NSDictionary *temp = [self.tweets objectAtIndex:indexPath.row];
NSDictionary *tweet = [self nullFreeDictionaryWithDictionary:temp];
cell.title.text = [tweet objectForKey:#"title"];
cell.views.text = [tweet objectForKey:#"views"];
return cell;
}
- (NSDictionary *)nullFreeDictionaryWithDictionary:(NSDictionary *)dictionary
{
NSMutableDictionary *replaced = [NSMutableDictionary dictionaryWithDictionary:dictionary];
// Iterate through each key-object pair.
[dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id object, BOOL *stop) {
// If object is a dictionary, recursively remove NSNull from dictionary.
if ([object isKindOfClass:[NSDictionary class]]) {
NSDictionary *innerDict = object;
replaced[key] = [NSDictionary nullFreeDictionaryWithDictionary:innerDict];
}
// If object is an array, enumerate through array.
else if ([object isKindOfClass:[NSArray class]]) {
NSMutableArray *nullFreeRecords = [NSMutableArray array];
for (id record in object) {
// If object is a dictionary, recursively remove NSNull from dictionary.
if ([record isKindOfClass:[NSDictionary class]]) {
NSDictionary *nullFreeRecord = [NSDictionary nullFreeDictionaryWithDictionary:record];
[nullFreeRecords addObject:nullFreeRecord];
}
else {
if (object == [NSNull null]) {
[nullFreeRecords addObject:#""];
}
else {
[nullFreeRecords addObject:record];
}
}
}
replaced[key] = nullFreeRecords;
}
else {
// Replace [NSNull null] with nil string "" to avoid having to perform null comparisons while parsing.
if (object == [NSNull null]) {
replaced[key] = #"";
}
}
}];
return [NSDictionary dictionaryWithDictionary:replaced];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 397;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
int storyIndex = [indexPath indexAtPosition: [indexPath length] - 1];
NSString * storyLink = [[tweets objectAtIndex: storyIndex] objectForKey:#"link"];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:storyLink]];
// Spit out some pretty JSON for the tweet that was tapped. Neato.
NSString *formattedJSON = [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:[self.tweets objectAtIndex:indexPath.row] options:NSJSONWritingPrettyPrinted error:nil] encoding:NSUTF8StringEncoding];
NSLog(#"tweet:\n%#", formattedJSON);
}
#end
Before I installed the new Xcode 5 I didn't get this error. Can someone help me?
Thanks.
What I've been doing myself to avoid this when parsing JSON results is replacing each instance of NSNull with a null string (#""), using the following method:
+ (NSDictionary *)nullFreeDictionaryWithDictionary:(NSDictionary *)dictionary
{
NSMutableDictionary *replaced = [NSMutableDictionary dictionaryWithDictionary:dictionary];
// Iterate through each key-object pair.
[dictionary enumerateKeysAndObjectsUsingBlock:^(id key, id object, BOOL *stop) {
// If object is a dictionary, recursively remove NSNull from dictionary.
if ([object isKindOfClass:[NSDictionary class]]) {
NSDictionary *innerDict = object;
replaced[key] = [NSDictionary nullFreeDictionaryWithDictionary:innerDict];
}
// If object is an array, enumerate through array.
else if ([object isKindOfClass:[NSArray class]]) {
NSMutableArray *nullFreeRecords = [NSMutableArray array];
for (id record in object) {
// If object is a dictionary, recursively remove NSNull from dictionary.
if ([record isKindOfClass:[NSDictionary class]]) {
NSDictionary *nullFreeRecord = [NSDictionary nullFreeDictionaryWithDictionary:record];
[nullFreeRecords addObject:nullFreeRecord];
}
else {
if (object == [NSNull null]) {
[nullFreeRecords addObject:#""];
}
else {
[nullFreeRecords addObject:record];
}
}
}
replaced[key] = nullFreeRecords;
}
else {
// Replace [NSNull null] with nil string "" to avoid having to perform null comparisons while parsing.
if (object == [NSNull null]) {
replaced[key] = #"";
}
}
}];
return [NSDictionary dictionaryWithDictionary:replaced];
}
Of course, this relies on the JSON return format being a dictionary, but you could easily modify it to accommodate other data types if you replaced all the parameter types with id and performed class checks.
--Edit--
If this is the only place you'll be using JSON, then change
NSDictionary *tweet = [self.tweets objectAtIndex:indexPath.row];
to
NSDictionary *temp = [self.tweets objectAtIndex:indexPath.row];
NSDictionary *tweet = [NSDictionary nullFreeDictionaryWithDictionary:temp];
Note that I have nullFreeDictionaryWithDictionary as an Objective-C category for the NSDictionary class. You could probably just add that to your view controller's implementation file if you weren't going to use this method anywhere else.
I would have thought 'self.data=' would retain the autorelease NSMutableArray objects and the NSMutableDictionary objects it contains, but eventually I get EXC_BAD_ACCESS when the table's cellForRowAtIndexPath method tries to access the NSDictionaries in self.data.
#property (strong, nonatomic) NSMutableArray *data;
- (void) updateReceivedData:(NSData *) jsonData
{
NSMutableArray *fetchedData = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
self.data = [self convertDates:fetchedData withFormat:kMySQLDateTimeFormat];
[self.tableView reloadData];
}
}
- (NSMutableArray*) convertDates:(NSMutableArray *) array withFormat:(NSString *) format
{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:format];
NSMutableArray *newArray = [NSMutableArray arrayWithArray:array];
for (NSMutableDictionary *dict in newArray)
{
for (id key in dict.allKeys)
{
if ([[dict objectForKey:key] isKindOfClass:[NSString class]])
{
NSString *value = [dict objectForKey:key];
NSDate *date = [dateFormatter dateFromString:value];
if (date) [dict setObject:date forKey:key];
}
}
}
[dateFormatter release];
return newArray;
}
BAD_ACCESS HERE thrown here between the NSLogs.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"cell";
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSLog (#"Cell was nil");
cell = [[[CustomCell alloc] init] autorelease];
}
NSDictionary *dict = [[NSDictionary alloc] init];
if (_isFiltered){
dict = [self.filteredData objectAtIndex:indexPath.row];
} else {
dict = [self.data objectAtIndex:indexPath.row];
}
NSLog (#"Filling Label 1");
cell.IDLabel.text = [[dict objectForKey:#"Id"] stringValue];
NSLog (#"Filling Label 2");
cell.firstNameLabel.text = [dict objectForKey:#"firstName"];
[dict release];
return cell;
}
Turn on zombies and see if it catches the problem (EXC_BAD_ACCESS does not necessarily mean an over-released object, but it might).
What happens to the absolute value of the retain count of an object is irrelevant.
However, a strong property implies that the object is retained, yes, if you assign through the setter (i.e. self.data = ... and not _data = ...).
Why are you releasing the dict in cellForRowAtIndexPath: . Eventhough you allocate dict, you are assigning another pointer which is an object from filteredData or data. Just remove the [data release] and while declaring data assign it as nil
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"cell";
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSLog (#"Cell was nil");
cell = [[[CustomCell alloc] init] autorelease];
}
// **As you will be assigning the object from filteredData/data, don't allocate here**
NSDictionary *dict = nil;
if (_isFiltered){
dict = [self.filteredData objectAtIndex:indexPath.row];
} else {
dict = [self.data objectAtIndex:indexPath.row];
}
NSLog (#"Filling Label 1");
cell.IDLabel.text = [[dict objectForKey:#"Id"] stringValue];
NSLog (#"Filling Label 2");
cell.firstNameLabel.text = [dict objectForKey:#"firstName"];
// **Release not required as you didn't allocate**
//[dict release];
return cell;
}
I have a UITableView that populates the results of a search that the user looks up. In order to do this I am using a NSMutableArray of Dictionaries where objects are added for the first 10, and then when the user scrolls to the bottom it populates the next 10 until there are no results left to show.
This all works well and good but I started to notice that the more searches that are done, the slower the table gets. Here is some of the code:
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
[self.objectsArray removeAllObjects];
[self.objectsArray setArray:nil];
[itemsTable reloadData];
[itemsTable scrollRectToVisible:CGRectMake(0, 0, 0, 0) animated:false];
[self loadItemsFromURL:searchURL withItemDescription:encodedString atStartRow:start andEndRow:end];
}
The above is when a new search is performed. It then does a NSURLConnection and responds with this:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
if (self.objectsArray == nil)
self.objectsArray = [NSMutableArray array];
// self.objectsArray = [[NSMutableArray alloc] init];
NSError *error;
NSDictionary *returnArray = [[NSJSONSerialization JSONObjectWithData:itemsData options:kNilOptions error:&error] valueForKey:#"items"];
for (id key in returnArray)
{
[self.objectsArray addObject:[returnArray objectForKey:key]];
}
counter += 10;
[itemsTable reloadData];
}
As you can see, if a user conducts a new search all objects are removed with [self.objectsArray removeAllObjects]and I even try to set the array to nil. If I perform multiple searches the UITableView gets slower and slower with scrolling each time. It is almost like the controller sees the array as getting larger and larger with each search even though I am removing all of the objects from it before the search. Any ideas or am I going about this the wrong way?
EDIT:
Here is the cellForRowAtIndexPath: method. cell is a subclassed UITableViewCell.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Product Cell";
static NSString *LoadCellIdentifier = #"Loading Cell";
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if ([self.objectsArray count] <= 0 )
{
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell.itemName.text = #"No items found.";
cell.itemPrice.text = #"";
cell.itemLocation.text = #"";
cell.addButton.hidden = YES;
}
else
{
if ([indexPath row] == [self.objectsArray count])
{
if ( [self.objectsArray count] >= 10 )
{
if ( [self.objectsArray count] < counter)
{
cell = [tableView dequeueReusableCellWithIdentifier:LoadCellIdentifier];
[cell.loadingSpinner stopAnimating];
cell.itemName.text = #"No more items found.";
}
else
{
if (!running)
{
[self loadItemsFromURL:searchURL withItemDescription:encodedString atStartRow:[self.objectsArray count] + 1 andEndRow:[self.objectsArray count] + 10];
cell = [tableView dequeueReusableCellWithIdentifier:LoadCellIdentifier];
cell.itemName.text = #"Loading more items...";
[cell.loadingSpinner startAnimating];
running = true;
}
else
{
cell = [tableView dequeueReusableCellWithIdentifier:LoadCellIdentifier];
[cell.loadingSpinner startAnimating];
}
}
}
}
else
{
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSArray *match = [self.objectsArray objectAtIndex:[indexPath row]];
cell.addButton.hidden = NO;
if ([match valueForKey:#"DESCRIPTION"] == [NSNull null] )
{
cell.itemName.text = #"Description not available.";
}
else
{
cell.itemName.text = [match valueForKey:#"DESCRIPTION"];
}
if ([match valueForKey:#"AD"] != [NSNull null])
{
NSMutableString *adString = [NSMutableString stringWithString:[match valueForKey:#"AD"]];
NSRange textRange;
textRange = [adString rangeOfString:#"1/"];
if (textRange.location != NSNotFound)
{
[adString replaceCharactersInRange:[adString rangeOfString:#"1/"] withString:#"$"];
}
else
{
[adString replaceCharactersInRange:[adString rangeOfString:#"/"] withString:#"/$"];
}
cell.itemPrice.text = adString;
}
else if ([match valueForKey:#"REGULAR"] == [NSNull null])
{
cell.itemPrice.text = #"$ N/A";
}
else
{
NSNumberFormatter *currencyStyle = [[NSNumberFormatter alloc] init];
[currencyStyle setFormatterBehavior:NSNumberFormatterBehavior10_4];
[currencyStyle setNumberStyle:NSNumberFormatterCurrencyStyle];
NSNumber *price = [NSNumber numberWithDouble:[[match valueForKey:#"REGULAR"] doubleValue]];
NSString *stringPrice = [currencyStyle stringFromNumber:price];
cell.itemPrice.text = [NSString stringWithFormat:#"%#", stringPrice];
}
if ([match valueForKey:#"AISLE"] == [NSNull null])
{
cell.itemLocation.text = #"Item location: N/A";
}
else
{
cell.itemLocation.text = [NSString stringWithFormat:#"Item Location: %#", [match valueForKey:#"AISLE"]];
}
match = nil;
}
}
return cell;
}
EDIT 2:
Here is a snippet of what the JSON looks like:
{
items = {
263149 = {
AD = "###";
AISLE = 6A;
DESCRIPTION = "Cinnamon Toasters";
R = 9;
REGULAR = "#.##";
};
26599 = {
AD = "####";
AISLE = 6A;
DESCRIPTION = "Quaker Life Cereal";
R = 2;
REGULAR = "#.##";
};
40517 = {
AD = "###";
AISLE = 6A;
DESCRIPTION = "Toasted Oats";
R = 1;
REGULAR = "#.##";
};
};
};
Ok, I think your problem is the excessive creation of Array objects. So do the following instead of you're array creation:
NSDictionary *returnArray = [[NSJSONSerialization JSONObjectWithData:itemsData options:kNilOptions error:&error] valueForKey:#"items"];
for (NSDictionary *dict in returnArray in returnArray)
{
[self.objectsArray addObject:dict];
}
counter += 10;
[itemsTable reloadData];
What you'll get as you see is an array of NSDictionary objects, your return array is already an NSDictionary of dictionary objects. Also, slight observation, where are you resetting your counter?
EDIT: creating the NSDictionary from NSData:
[NSJSONSerialization JSONObjectWithData:self.requestData options:NSJSONReadingMutableContainers | NSJSONReadingMutableLeaves error:&error]
The requestData is generated using these delegate methods:
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSLog(#"In didReceiveResponse");
[self.requestData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSLog(#"In didReceiveData");
[self.requestData appendData:data];
}
I was able to find the issue in one line in the cellForRowAtIndexPath:. I commented out: cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; at the top and made sure it was only called once. I also did do a bit of cleanup as suggested by 8vius and now only once NSString is being allocated in that method call. Once I did these two things it was nice and responsive again without any stutters.
I am new to iphone development, I am trying to load a NSMutableArray values into a table view, I am using code below for this which generates error as specified. Can some one help me in rectifying this error.
code :-
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return [ShowList count];
}
// Customize the appearance of table view cells.
- (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];
}
// Configure the cell...
NSString *cellValue = [ShowList objectAtIndex:indexPath.row];
cell.textLabel.text = cellValue;
return cell;
}
error :-
2011-02-25 07:22:24.470 iPhone[1032:207] -[__NSArrayM isEqualToString:]: unrecognized selector sent to instance 0xab15d30
2011-02-25 07:22:24.471 iPhone[1032:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayM isEqualToString:]: unrecognized selector sent to instance 0xab15d30'
*** Call stack at first throw:
Print Description of My NSMutableArray :-
2011-02-25 07:21:54.806[1032:207] (
(
"viral_tweeter",
default1571546,
default1570056,
twilightsaga,
"wp-monetizer",
viraltweetbuild,
"building_a_list",
yourtwittertips,
"twitter_profit",
mikesbi,
mikesbizz,
default1164341,
incbizztest,
default1164319,
iprotv,
iwantafreecopy1,
tweeterbuilder,
trafficlists,
myadsensenews,
mysafelistnews,
myviralnews,
safelistology,
slmembers,
slpmembers,
twonderlandlist,
noseospider,
yseospider,
digitallockdown,
alistblueprint,
classifiedtips,
incbizzblog,
"xit-trafficbeta",
twwidget,
jvtrafficfunnel,
instantmlmspage,
listbuldingmax,
"incbizz_tips"
)
)
code for parsing HTTP Get response :-
- (void)requestDataFetcher:(GTMHTTPFetcher *)fetcher finishedWithData:(NSData *)data error:(NSError *)error {
// this is only for testing whether the data is coming or not
// NSDictionary *tempDict = [GTMOAuthAuthentication dictionaryWithResponseData:data];
if (error)
{
NSLog(#"Error: in getting data after authentication : %#",[error description]);
}
else
{
// NSLog(#"Succcess: in getting data after authentication \n data: %#",[tempDict description]);
NSString* aStr;
aStr = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSDictionary *dictionary = [aStr JSONValue];
NSArray *keys = [dictionary allKeys];
Names = [[NSMutableArray alloc]init];
int i = 0;
// values in foreach loop
for (NSString *key in keys)
{
i++;
NSArray *items = (NSArray *) [dictionary objectForKey:key];
// NSLog(#" test %#", items);
if (i==3)
{
for (NSString *item in items)
{
NSString* aStrs= item;
// NSLog(#" test %#", aStrs);
NSDictionary *dict = aStrs;
NSArray *k = [dict allKeys];
for (id *it in k)
{
// NSLog(#"the child item: %#", [NSString stringWithFormat:#"Child Item -> %# value %#", (NSDictionary *) it,[dict objectForKey:it]]);
NSString *value = [it description];
if ( [value isEqualToString:#"name"])
{
NSString * value = (NSString*)[[dict objectForKey:it] description];
NSLog(value);
[Names addObject:value];
[[MySingletonClass sharedMySingleton] SetAweberList: value];
}
}
}
}
}
mShowList.hidden = FALSE;
}
}
#Ravi your array is array of array that is the ShowList is an array which has first object as array and that array is that
"viral_tweeter",
default1571546,
default1570056,
twilightsaga,
"wp-monetizer",
viraltweetbuild,
"building_a_list",
yourtwittertips,
"twitter_profit",
mikesbi,
mikesbizz,
default1164341,
incbizztest,
default1164319,
iprotv,
iwantafreecopy1,
tweeterbuilder,
trafficlists,
myadsensenews,
mysafelistnews,
myviralnews,
safelistology,
slmembers,
slpmembers,
twonderlandlist,
noseospider,
yseospider,
digitallockdown,
alistblueprint,
classifiedtips,
incbizzblog,
"xit-trafficbeta",
twwidget,
jvtrafficfunnel,
instantmlmspage,
listbuldingmax,
"incbizz_tips"
so you can do something like this.
NSString *cellValue = [[ShowList objectAtIndex:0] objectAtIndex:indexPath.row];
I assume UILabel's setText calls isEqualToString for some reason, so it crashes for the very first object in your array which is not a NSString.