Why is my NSMutableArray deallocating in UITableView - uitableview

My NSMutableArray seems to be releasing and I can't figure out where, here is my code:
- (void)awakeFromNib {
arrayOfData = [[NSMutableArray alloc] initWithCapacity:0];
[arrayOfData addObject:#"test"];
NSLog(#"array: %#", arrayOfData);
}
All is well here!
Then I create a UITable and add it to the view, then I request some data, everything is normal.
arrayOfData = [response objectForKey:#"results"];
NSLog(#"count: %i", [arrayOfData count]);
NSLog(#"success!");
numberOfRows = [arrayOfData count];
[self.myTableView reloadData];
Creating the number of rows works fine too:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(#"test: %i", numberOfRows);
return numberOfRows;
}
Now accessing my array gets a "message sent to deallocated instance" at that line.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:MyIdentifier] autorelease];
}
// crashes here!
NSLog(#"array: %i", [arrayOfData count]);
if (numberOfRows){
NSString *filename = [[arrayOfData objectAtIndex:indexPath.row] objectForKey:#"filename"];
NSString *url = [NSString stringWithFormat: #"http://www.web.com/dir/%#", filename];
[cell.imageView setImageWithURL:[NSURL URLWithString:url]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
cell.textLabel.text = #"My Text";
}
return cell;
}
I have also have this in my header, and I used #synthesize as well
#property (nonatomic, retain) NSMutableArray *arrayOfData;
Any help would be appreciated!

It looks like you're reassigning arrayOfData with this line:
arrayOfData = [response objectForKey:#"results"];
If that's what you want, try this instead:
arrayOfData = [[response objectForKey:#"results"] retain];

Related

I am trying to display detail list of may json response in UITableViewcell

Hi I am trying to display detail information of json data in second table view but their is some mistake in my logic so please help me my json response is in image and I am trying to to dispaly channel response in table view when user click the same cat_id then display all related channel list and image in second tableViewcell please help me..
-(void)getCategories
{
Service *srv=[[Service alloc]init];
NSString *str=#"http://streamtvbox.com/site/api/matrix/";//?country_code=91&phone=9173140993&fingerprint=2222222222";
NSString *method=#"channels";
NSMutableDictionary *dict=[[NSMutableDictionary alloc]init];
[srv postToURL:str withMethod:method andParams:dict completion:^(BOOL success, NSDictionary *responseObj)
{
NSDictionary *dict = [[NSDictionary alloc]initWithDictionary:[responseObj valueForKey:#"categories"]];
arrayChannelList=[responseObj valueForKey:#"channels"];
NSLog(#"Array : %#",channels);
for (NSDictionary *dict in arrayChannelList)
{
//NSArray *tempTitle = [[NSArray alloc]init];
arrayCat_Id = [dict objectForKey:#"cat_id"];
}
tempArray = [[NSArray alloc]init];
tempArray = [dict allKeys];
for(int i=0; i<tempArray.count; i++)
{
[arrayCategories addObject:[dict valueForKey:[tempArray objectAtIndex:i]]];
}
NSLog(#"%#",arrayCategories);
[tblView reloadData];
}];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"%lu",(unsigned long)[arrayCategories count]);
return arrayCategories.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"ChannelCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = [arrayCategories objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
DetailChannelsViewController *detailVC = (DetailChannelsViewController *)[self.storyboard instantiateViewControllerWithIdentifier:#"DetailView"];
detailVC.channelTitle = [arrayCategories objectAtIndex:indexPath.row];
detailVC.SubChannelName = arrayCat_Id;
NSLog(#"%#",arrayCat_Id);
[self.navigationController pushViewController:detailVC animated:YES];
}
Just initialize of your NSmutuableArray and add the value of with addobject like:-
arrayCat_Id=[[NSMutableArray alloc]init];
for(your logic){
[arrayCat_Id addobject:[dict objectForKey:#"cat_id"];
}

Error: '-[__NSCFArray removeObjectAtIndex:]: mutating method sent to immutable object'

I'm attempting to allow my user to be able to delete/remove a row from a tableView (remove an object from an existing NSMutableArray), however when I try and delete the row, I get the following crash error:
Terminating app due to uncaught exception
'NSInternalInconsistencyException', reason: '-[__NSCFArray
removeObjectAtIndex:]: mutating method sent to immutable object'
Does anyone know why this might be? See code below. Apologies for the lengthy code.
.h
#property (strong, nonatomic) NSMutableArray *descripData;
.m
- (void)viewDidLoad {
[super viewDidLoad];
self.descripData = [[NSMutableArray alloc] init];
refreshControl = [[UIRefreshControl alloc]init];
[self.tableView addSubview:refreshControl];
[refreshControl addTarget:self action:#selector(refreshTable) forControlEvents:UIControlEventValueChanged];
NSMutableDictionary *viewParams = [NSMutableDictionary new];
[viewParams setValue:#"storeditems" forKey:#"view_name"];
[DIOSView viewGet:viewParams success:^(AFHTTPRequestOperation *operation, id responseObject) {
self.descripData = responseObject;
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Failure: %#", [error localizedDescription]);
}];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if ([self.storageData count] > 0 && self.descripData.count > 0)
{
return [self.descripData count];
}
else
return 0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *DoctorsTableIdentifier = #"StorageItemTableViewCell";
StorageItemTableViewCell *cell = (StorageItemTableViewCell *)[tableView dequeueReusableCellWithIdentifier:DoctorsTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"StorageItemTableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
if (self.storageData.count > 0 && self.descripData.count > 0) {
noitemsView.hidden = YES;
NSDictionary *title = [self.descripData objectAtIndex:indexPath.row];
[[cell itemName] setText:[title objectForKey:#"node_title"]];
NSDictionary *node = [self.descripData objectAtIndex:indexPath.row];
[[cell itemDescrip] setText:[node objectForKey:#"body"]];
NSDictionary *value = [self.descripData objectAtIndex:indexPath.row];
[[cell valueLabel] setText:[value objectForKey:#"dollarvalue"]];
NSLog(#"%#", self.descripData);
NSDictionary *quantity = [self.descripData objectAtIndex:indexPath.row];
[[cell quantityLabel] setText:[quantity objectForKey:#"quantity"]];
NSLog(#"%#", self.descripData);
NSString *secondLink = [[self.descripData objectAtIndex:indexPath.row] objectForKey:#"photo"];
[cell.itemPhoto sd_setImageWithURL:[NSURL URLWithString:secondLink]];
}
else {
noitemsView.hidden = NO;
}
return cell;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 152;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source
[self.descripData removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView reloadData];
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ItemDetailViewController *detailViewController = [[ItemDetailViewController alloc] initWithNibName:#"ItemDetailViewController" bundle:nil];
detailViewController.itemDetail = [[values objectAtIndex:indexPath.row] objectForKey:#"node_title"];
detailViewController.itemDetail = [self.descripData objectAtIndex:indexPath.row];
detailViewController.secondLink = self.descripData[indexPath.row][#"photo"];
[self.navigationController pushViewController:detailViewController animated:YES];
}
Check the line self.descripData = responseObject;. It looks like you are probably setting your descripData property to point to a NSArray, not an NSMutableArray. If you really need the mutability, try self.descripData = [responseObject mutableCopy]; instead.
I suspect that the following assignment causes the problem:
self.descripData = responseObject;
The response object itself is immutable, assigning it to a NSMutableArray does not change that fact, you need to create a NSMutableArray with the contents of the responseObject:
self.descripData = [NSMutableArray arrayWithArray:responseObject];
Most likely happening on the following line:
self.descripData = responseObject;
You're replacing your previous mutable array for descripData with a new one, which apparently is not mutable. You can either create a new mutable array from this new array using [NSMutableArray arrayWithArray:responseObject], or you can add the contents of responseObject to your current mutable array.
It's important to pay attention when you assign something of type id to a variable, because there's no compile-time type checking that can occur. This sometimes results in errors at runtime.
Face this issue because NSUserDefaults always returns an immutable object.
Please while retrieving Mutable object from NSUserDefaults please refer below code.
NSMutableArray *storeArray = [[defaultDefects objectForKey:#"defaultStoreDefects"]mutableCopy];

Terminating app due to uncaught exception 'NSRangeException', reason: -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array' - 2

working as a new person in json i want to show data in tableview cell but when i am populating my table view cell it is giving an exception mentioned above. i had asked this question previously but not get exact solution
i am getting response like this in view did load
-(void)inboxmessagesGetSuccess:(FBGenericWebHandler*)handler response:(NSDictionary*)response
{
NSLog (#"Count %d", [[response objectForKey:#"messageResponse"] length] );
NSMutableArray *inboxArray = [[NSMutableArray alloc] init];
NSArray *firstarray=[[[response objectForKey:#"messageResponse"] objectAtIndex:1] objectForKey:#"messages"];
for(NSDictionary *tmp in firstarray)
{
NSMutableDictionary *messages=[[NSMutableDictionary alloc]init];
[messages setValue:[tmp objectForKey:#"messageId"] forKey:#"messageId"];
// [self.inboxmessagesarray addObject:messages];
}
[self.activitiesTableView_ reloadData];
}
but when i populate my cell
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *tableviewidentifier = #"cell";
tablecellTableViewCell *cell= [self.activitiesTableView_ dequeueReusableCellWithIdentifier:tableviewidentifier];
if(cell==nil)
{
cell = [[tablecellTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:tableviewidentifier];
}if(indexPath.row == [self tableView:tableView numberOfRowsInSection:indexPath.section] - 1){
// [[cell textLabel] setText:#"Load more records"];
}
UILabel *valuedate = (UILabel *)[cell viewWithTag:21];
UILabel *msg = (UILabel *)[cell viewWithTag:22];
UILabel *date = (UILabel *)[cell viewWithTag:23];
UILabel *time = (UILabel *)[cell viewWithTag:24];
valuedate.text=[[self.inboxmessagesarray objectAtIndex:indexPath.row]objectForKey:#"messageId"];
return cell;
}
it is giving an exception . thanx in advance really stuck in it for many days.
Change your self.lblArray for loop into inboxmessagesGetSuccess method
-(void)inboxmessagesGetSuccess:(FBGenericWebHandler*)handler response:(NSDictionary*)response
{
NSMutableArray *inboxArray = [[NSMutableArray alloc] init];
NSArray *firstarray=[[[response objectForKey:#"messageResponse"] objectAtIndex:1] objectForKey:#"messages"];
for(NSDictionary *tmp in firstarray)
{
NSMutableDictionary *messages=[[NSMutableDictionary alloc]init];
[messages setValue:[tmp objectForKey:#"messageId"] forKey:#"messageId"];
[self.inboxmessagesarray addObject:messages];
}
for (int i=0; i<self.inboxmessagesarray.count; i++)
{
[self.lblArray addObject:[NSString stringWithFormat:#"cell Number %d",i]];
}
[self.activitiesTableView_ reloadData];
}
Try this
-(void)inboxmessagesGetSuccess:(FBGenericWebHandler*)handler response:(NSDictionary*)response
{
if(response && response[#"messageResponse"])
{
NSArray *messageResponseList = response[#"messageResponse"];
if(messageResponseList && [messageResponseList count]>=1)
{
NSLog (#"Count %lu", (unsigned long)[messageResponseList count]);
NSMutableArray *inboxArray = [[NSMutableArray alloc] init];
NSDictionary *message = [messageResponseList objectAtIndex:1];
if(message && message[#"messages"])
{
NSArray *firstarray=[[messageResponseList objectAtIndex:1] objectForKey:#"messages"];
for(NSDictionary *tmp in firstarray)
{
NSMutableDictionary *messages=[[NSMutableDictionary alloc]init];
[messages setValue:[tmp objectForKey:#"messageId"] forKey:#"messageId"];
[self.inboxmessagesarray addObject:messages];
}
}
}
}
[self.activitiesTableView_ reloadData];
}
instead of having:
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.lblArray.count;
}
u should probably have:
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.inboxmessagesarray.count;
}
As it is now, your tableview tries to populate when app loads before -(void)inboxmessagesGetSuccess:(FBGenericWebHandler*)handler response:(NSDictionary*)response method gets called, so your inboxmessagesarray is empty at this point, but your datasource is telling uitableview that it should have lblArray.count cells, and that array isn't empty.

Cell for row at indexpath only called once

I am parsing a json data and in that one of the field is an array if it has a content.But if it has no content it is simply a string "No result."
I am using the following code to parse it :
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
//URL is called.
if ([status isEqualToString:#"success"])
{
if ([[[json objectForKey:#"Items"] objectForKey:#"item_list"] isKindOfClass:[NSString class]])
{
_Label.text = [NSString stringWithFormat:#"0"];
ItemsArray = [[NSMutableArray alloc]init];
}
else
{
ItemsArray = [[json objectForKey:#"Items"] objectForKey:#"item_list"];
NSLog(#"%d",[ItemsArray count]);
float Amount = 0;
NSLog(#"%d",[ItemsArray count]);
if ([ItemsArray count]>0)
{
for (int i=0; i<[ItemsArray count]; i++)
{
NSMutableDictionary * temp3 = [ItemsArray objectAtIndex: i];
NSString * x = [temp3 objectForKey:#"final"];
Amount = Amount + [x floatValue];
}
Label.text = [NSString stringWithFormat:#"%.2f",BidAmount];
}
else
{
Label.text = [NSString stringWithFormat:#"0"];
}
}
[TableViewOutlet reloadData];
}
This works fine.
When the field returns string i face no problem.But when the field is an array,I am stuck.
After running the project for the first time it works fine even if the array count is more than 0.But from second time onwards the Cellforrowatindexpath method is not called even when array count is more than 0....
These are my codes:
-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"%d",[ItemsArray count]);
return [ItemsArray count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"TableViewCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell==nil)
{
cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.backgroundColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.025];
NSDictionary *temp = [ItemsArray objectAtIndex:indexPath.row];
UILabel *ItemName = (UILabel *)[cell viewWithTag:1000];
ItemName.text = [temp objectForKey:#"title"];
UILabel *Cost = (UILabel *)[cell viewWithTag:1001];
Cost.text = [temp objectForKey:#"final"];
return cell;
}
Someone please help me
I think the issue is that you have not retained your ItemArray.
NSArray* array = [[json objectForKey:#"Items"] objectForKey:#"item_list"];
ItemsArray = [NSMutableArray alloc]]initWithArray:array];
Use this code snippet..hope it will work.

How do you load multiple arrays into a UITableView?

I am calling some JSON and loading a table with the data from a single array. That's working great. Now I'm trying to figure out
A. the best way to load the data into the table and
B. the best way to section that data off.
This is my 6th week of iOS development and I am pretty new. I have a fairly weak Javascript background.
My first (failed attempt) way to concatenate the arrays together and pass that to the tableview. I think this is wrong for multiple reasons (issues with sectioning afterwards, know "which" one to delete, etc). Any help is greatly appreciated!
Didn't work:
NSDictionary *dataDictionary = [NSJSONSerialization JSONObjectWithData:responseObject options:0 error:&errorJson];
self.allGroups = [dataDictionary objectForKey:#"all_groups"]; //NSDictionary
self.firstGroup = [self.allGroups objectForKey:#"first_group"]; //NSMutableArray
self.secondGroup = [self.allGroups objectForKey:#"second_group"]; //NSMutableArray
self.thirdGroup = [self.allGroups objectForKey:#"third_group"]; //NSMutableArray
NSMutableArray *allGroupsArray = [self.firstGroup arrayByAddingObjectsInArray:[self.secondGroup arrayByAddingObjectsInArray:self.thirdGroup]];
Does work now, but can't figure out multiple arrays into the tableview:
-(void) getTheData {
NSString *sessionToken = [[AFOAuthCredential retrieveCredentialWithIdentifier:#"myToken"] accessToken];
if (sessionToken == nil) {
LoginViewController *loginView = [[LoginViewController alloc] init];
[self presentViewController:loginView animated:NO completion:nil];
return;
}
NSURL *url = [NSURL URLWithString:#"https://greatwebsitetogetdata.com"];
AFOAuth2Client *oauthClient = [AFOAuth2Client clientWithBaseURL:url clientID:#"MY_CLIENT" secret:#"1234567890abc"];
[oauthClient getPath:#"/api/v1/json" parameters:#{#"access_token": sessionToken} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSError *errorJson = nil;
NSDictionary *dataDictionary = [NSJSONSerialization JSONObjectWithData:responseObject options:0 error:&errorJson];
self.allGroups = [dataDictionary objectForKey:#"all_groups"]; //This is a NSDictionary
self.firstGroup = [self.allGroups objectForKey:#"first_group"]; //This is a NSMutableArray
self.secondGroup = [self.allGroups objectForKey:#"second_group"]; //This is a NSMutableArray
self.thirdGroup = [self.allGroups objectForKey:#"third_group"]; //This is a NSMutableArray
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.firstGroup.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *groupInfo = self.firstGroup[indexPath.row];
static NSString *cellIdentifier = #"Cell";
groupTableViewCell *cell = (groupTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[groupTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.groupTitle.text= groupInfo[#"title"];
cell.groupLikes.text= [NSString stringWithFormat:#"%#", groupInfo[#"likes"]];
cell.groupRunDates.text= [NSString stringWithFormat:#"%# - %#", groupInfo[#"start_date"], groupInfo[#"end_date"]];
cell.groupAcceptance.text= groupInfo[#"acceptance_type"];
return cell;
}
I think an array of arrays would work better for you, where each array represents a section. allGroups should then contain 3 arrays.
Then you need to override the datasource method:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return self.allGroups.count;
}
and then in:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.allGroups[section];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSArray *group = self.allGroups[indexPath.section];
NSDictionary *groupInfo = group[indexPath.row];
static NSString *cellIdentifier = #"Cell";
groupTableViewCell *cell = (groupTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[groupTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.groupTitle.text= groupInfo[#"title"];
cell.groupLikes.text= [NSString stringWithFormat:#"%#", groupInfo[#"likes"]];
cell.groupRunDates.text= [NSString stringWithFormat:#"%# - %#", groupInfo[#"start_date"], groupInfo[#"end_date"]];
cell.groupAcceptance.text= groupInfo[#"acceptance_type"];
return cell;
}

Resources