Custom UICollectionViewCell not loading - ios

I'm using a storyboard and my custom UICollectionViewCell is not appearing. I played around with it for a few hours and have googled a ton of different solutions but none worked. Just to clarify, the data exists, and the UICollectionView is appearing, but the cell is not. Here is my code. Any suggestions would be appreciated!
- (NSInteger)collectionView:(UICollectionView *)mutualFriendsView numberOfItemsInSection:(NSInteger)section {
return [self.resultsDictionary count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)mutualFriendsView
cellForItemAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = #"PCRRequesterMutualFriendsCollectionViewCell";
PCRRequesterMutualFriendsCollectionViewCell *cell = [self.mutualFriendsView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
NSArray *idArray = [self.resultsDictionary objectForKey:#"id"];
NSArray *nameArray = [self.resultsDictionary objectForKey:#"name"];
cell.profileName.text = [nameArray objectAtIndex:indexPath.row];
cell.backgroundColor = [UIColor redColor];
return cell;
}
- (void)collectionView:(UICollectionView *)mutualFriendsView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"cell #%d was selected", indexPath.row);
}
- (BOOL)shouldAutorotate {
[mutualFriendsView.collectionViewLayout invalidateLayout];
BOOL retVal = YES;
return retVal;
}
EDIT Here is my viewDidLoad
self.mutualFriendsView.dataSource = self;
self.mutualFriendsView.delegate = self;
self.mutualFriendsView.pagingEnabled = YES;
// [self.mutualFriendsView registerClass:[PCRMutualFriendsCollectionViewCell class] forCellWithReuseIdentifier:#"PCRMutualFriendsCollectionViewCell"];
Edit I think I figured out the problem. I don't think the dictionary is being populated after the completion block finishes. Any suggestions for saving the value of the dictionary from the block to be used outside of it?
__block NSMutableDictionary *mutualFriends = nil;
__block NSNumber *total;
NSString *u = [NSString stringWithFormat:#"%#",self.details[#"Requester"][#"profile"][#"facebookId"]];
/* make the API call */
[FBRequestConnection startWithGraphPath:(#"/%#", u)
parameters:params
HTTPMethod:#"GET"
completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
/* handle the result */
if (!error){
NSLog(#"RESULT OF FB %#", result);
if (result == nil){
NSLog(#"No shared friends");
} else {
total = result[#"context"][#"mutual_friends"][#"summary"][#"total_count"];
NSLog(#"TOTAL FRIENDS %#", total);
for(int i=0;i<[result[#"context"][#"mutual_friends"][#"data"] count];i++)
{
mutualFriends = result[#"context"][#"mutual_friends"][#"data"][i];
NSLog(#"FRIENDDATA %#", mutualFriends);
}
}
} else {
NSLog(#"ERROR %#", error);
}
}];
self.resultsDictionary = mutualFriends;
self.number = total;
NSLog(#"NUMBER %#", self.number);
NSLog(#"RESULTS DICTIONARY %#", self.resultsDictionary);
NSString *friends = [NSString stringWithFormat:#"You have %# friends in common including:", self.number];

After this code:
for(int i=0;i<[result[#"context"][#"mutual_friends"][#"data"] count];i++)
{
mutualFriends = result[#"context"][#"mutual_friends"][#"data"][i];
NSLog(#"FRIENDDATA %#", mutualFriends);
}
// add
self.resultsDictionary = mutualFriends;
mutualFriendsView.reloadData();
All within that completion block. So when FB finally does return and you've accumulated all the mutualFriends, then you tell the collectionView to reload.

Related

Application Termination because of NSRangeException (NSMutableArray)

I'm trying to retrieve uploaded thumbnailPhotos from Parse to display them in UITableViewCells, but I get an exception thrown in everytime. The error code is as follows: "Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0]'"
This is my code:
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
PFQuery *query = [PFQuery queryWithClassName:#"Events"];
[query orderByDescending:#"date"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
NSLog(#"Error: %# %#", error, [error userInfo]);
} else {
self.events = (NSMutableArray *) objects;
[self.tableView reloadData];
for (PFObject *event in self.events) {
NSInteger index = [self.events indexOfObject:event];
PFFile *imageFile = [event objectForKey:#"thumbnailImage"];
[imageFile getDataInBackgroundWithBlock:^(NSData *result, NSError *error) {
if (error) {
//Handle Error
} else {
UIImage *image = [UIImage imageWithData:result];
if (self.thumbnailPhotos == nil) {
self.thumbnailPhotos = [NSMutableArray array];
self.thumbnailPhotos[index] = image;
} else {
self.thumbnailPhotos[index] = image;
}
[self.tableView reloadData];
}
}];
}
}
}];
}
CellForRowAtIndexPath:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *reuseIdentifier = #"Cell";
EventsTableViewCell *cell = (EventsTableViewCell *)[tableView dequeueReusableCellWithIdentifier:reuseIdentifier forIndexPath:indexPath];
PFObject *event = [self.events objectAtIndex:indexPath.row];
NSDate *date = [event objectForKey:#"date"];
NSString *dateString = [self.dateFormat stringFromDate:date];
NSString *timeString = [self.timeFormat stringFromDate:date];
NSLog(#"IndexPath.row = %ld", (long)indexPath.row);
if ([self.thumbnailPhotos objectAtIndex:indexPath.row] != nil) {
cell.imageView.image = self.thumbnailPhotos[indexPath.row];
} else {
NSLog(#"Nil, Application will crash!");
}
cell.eventNameLabel.text = [event objectForKey:#"title"];
cell.dateLabel.text = dateString;
cell.timeLabel.text = timeString;
[cell.timeLabel sizeToFit];
return cell;
}`
I had to add the index value of self.events because the thumbnailPhotos were downloaded in different speed, so my Cells always showed the wrong photo for the wrong event.
I hope this was enough details to figure the problem out.
Application is crashing because thumbnailPhotos doesn't have any object at index for assignment. Please use following code.
Updated Code which will support Dictionary to hold thumbnail images
/*
Define events as NSMutableArray which holds all events
Define thumbnailPhotos as NSMutableDictionary which holds thumbnail image for index as key
*/
//Create a weak Reference of self for accessing self within block
__weak __typeof(self)weakSelf = self;
PFQuery *query = [PFQuery queryWithClassName:#"Events"];
[query orderByDescending:#"date"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error) {
NSLog(#"Error: %# %#", error, [error userInfo]);
} else {
//Create a strong reference for updating the UI
__strong __typeof(weakSelf)strongSelf = weakSelf;
//Assign the events to instance object
strongSelf.events = [NSMutableArray arrayWithArray:objects];
//Alloced thumbnail dictionary
strongSelf.thumbnailPhotos = [NSMutableDictionary dictionary];
//Reload tableView so that data will be visible
[strongSelf.tableView reloadData];
for (PFObject *event in strongSelf.events) {
//Define index as block type because we have to use this instance within block
__block NSInteger index = [strongSelf.events indexOfObject:event];
PFFile *imageFile = [event objectForKey:#"thumbnailImage"];
[imageFile getDataInBackgroundWithBlock:^(NSData *result, NSError *error) {
if (error) {
//Handle Error
} else {
UIImage *image = [UIImage imageWithData:result];
//Set the image against index
[strongSelf.thumbnailPhotos setObject:#"" forKey:#(index)];
//Reload only cell for which image is just downloaded
[strongSelf.tableView reloadRowsAtIndexPaths:#[[NSIndexPath indexPathForRow:index inSection:0]] withRowAnimation:UITableViewRowAnimationAutomatic];
}
}];
}
}
}];
Updated:
Modify your cellForRowAtIndexPath as below
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *reuseIdentifier = #"Cell";
EventsTableViewCell *cell = (EventsTableViewCell *)[tableView dequeueReusableCellWithIdentifier:reuseIdentifier forIndexPath:indexPath];
PFObject *event = [self.events objectAtIndex:indexPath.row];
NSDate *date = [event objectForKey:#"date"];
NSString *dateString = [self.dateFormat stringFromDate:date];
NSString *timeString = [self.timeFormat stringFromDate:date];
NSLog(#"IndexPath.row = %ld", (long)indexPath.row);
if ([self.thumbnailPhotos valueForKey:#(indexPath.row)]) {
cell.imageView.image = [self.thumbnailPhotos valueForKey:#(indexPath.row)];
} else {
NSLog(#"Nil, Application will crash!");
}
cell.eventNameLabel.text = [event objectForKey:#"title"];
cell.dateLabel.text = dateString;
cell.timeLabel.text = timeString;
[cell.timeLabel sizeToFit];
return cell;
}
In this implementation thumbnail Image is getting saved in to dictionary and second reload of tableView is per cell basis instead of reloading complete tableView for single thumbnail download.

UITableViewController [__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array' with PFTask thenCallBackOnMainThreadAsync:]

I am purposely creating a empty Array to not display anything on the UITablewView.
However, it gives me that error.
To debug, I even created an empty UITableViewController and refer storyboard file to this. However, it is giving me the same error.
I just tried and connect it with an empty UIViewController, it is giving me the same objectAtIndex error.
So I doubt it is the problem with the what I am indexing for cells.
When I run, the screen is shown but it throws the error and it freezes.
The declaration of the newsList is:
#property (strong, nonatomic)NSArray *newsList
This is what I have for the UITableViewController.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.currentUser = appDelegate.currentUser;
NSString *addNewsFeed = #"_NewsFeed";
if (self.currentUser)
{
if (appDelegate.selectedGroup == nil)
{
self.newsList = nil;
}
else
{
NSLog(#"SELECTED GROUP EXIST");
NSString *currentNewsFeed = [appDelegate.selectedGroup[#"name"] stringByAppendingString:addNewsFeed];
PFQuery *query = [PFQuery queryWithClassName:currentNewsFeed];
[query orderByDescending:#"createdAt"];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (error)
{
NSLog(#"Error: %#, %#", error, [error userInfo]);
}
else
{
self.newsList = objects;
[self.tableView reloadData];
}
}];
}
}
else
{
NSLog(#"%#", appDelegate.currentUser);
[self performSegueWithIdentifier:#"loginView" sender:self];
}
NSLog(#"ZXCVZCVZ: %#", self.newsList);
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
if (appDelegate.selectedGroup == nil)
{
NSLog(#"NO CELL HERE");
return 0;
}
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (appDelegate.selectedGroup == nil)
{
NSLog(#"NO CELL");
return 0;
}
return [self.newsList count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"NO LIST FOUND");
static NSString *CellIdentifier = #"News";
NSLog(#"DSFSDFSDFSFS");
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
PFObject *item = [self.newsList objectAtIndex:indexPath.row];
cell.textLabel.text = item[#"title"];
cell.detailTextLabel.text = item[#"news"];
return cell;
}
you need to allocate the memory for array as below
self.newsList=[[NSMutableArray alloc]init];//At viewWIllAppear
Without alloc the self.newsList you cannot able to store any records in it...
Hope it fixes...

Outputting read in NSMutable Array

Problem: I have read in values from Windows Azure. Through NSLogs I am able to see that my application does indeed read in from the table on the Azure Server. However Displaying the values has become a problem.
Situation: So far I have an NSMutableArray object in the ViewController.m file. I have accessed the array and been able to assign the values from the results of the read from the table (in windows azure) to the mutableArray. My problem is that I am trying to display it through a tableview however nothing displays, and when I move down the table view, the application crashes.
I believe the main problem is this line:
cell.textLabel.text = [clubs objectAtIndex:indexPath.row];
Here is the ViewController.m code:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController{
NSDictionary *courseDetails;
NSArray *justCourseNames;
NSDictionary *webcourseDetails;
NSArray *webjustCourseNames;
NSDictionary *clubNames;
NSArray *location;
NSMutableArray *clubs;
NSInteger amount;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 2;
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
if (section == 0)
{
return #"Milton Keynes";
}
else{
return #"Stafford";
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
if (section == 0)
{
return clubs.count;
}
else{
return webcourseDetails.count;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
UIImage *image = [UIImage imageNamed:#"ClubCellImage"];
[cell.imageView setImage:image];
//removing the line of code below seems to fix the crash. this is the line of code to display the details
cell.textLabel.text = [clubs objectAtIndex:indexPath.row];
/*if (indexPath.section == 0)
{
//cell.textLabel.text = justCourseNames[indexPath.row];
//cell.detailTextLabel.text = courseDetails[justCourseNames[indexPath.row]];
}
else
{
cell.textLabel.text = clubs[indexPath.row];
//cell.textLabel.text = webjustCourseNames[indexPath.row];
//cell.detailTextLabel.text = webcourseDetails[webjustCourseNames[indexPath.row]];
}*/
return cell;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.client = [MSClient clientWithApplicationURLString:#"https://clublocatortimogunmakin.azure-mobile.net/"
applicationKey:#"ecxnaXEfNpeOvwYYgcViJJoumZlZng45"];
// Do any additional setup after loading the view.
NSURL *url = [[NSBundle mainBundle] URLForResource:#"courses" withExtension:#"plist"];
MSTable *itemTable = [_client tableWithName:#"Item"];
courseDetails = [NSDictionary dictionaryWithContentsOfURL:url];
justCourseNames = courseDetails.allKeys;
NSURL *weburl = [[NSBundle mainBundle] URLForResource:#"courses_web" withExtension:#"plist"];
webcourseDetails = [NSDictionary dictionaryWithContentsOfURL:weburl];
webjustCourseNames = courseDetails.allKeys;
[itemTable readWithCompletion:^(NSArray *results, NSInteger totalCount, NSError *error) {
clubs = [results mutableCopy];
amount = totalCount;
if (error) {
NSLog(#"Error: %#", error);
} else {
//NSLog(#"Item read, id: %#", [results objectAtIndex:1]);
for (int i = 0; i < results.count; i++)
{
NSLog(#"Item read, id: %#", [results objectAtIndex:i]);
}
}
}];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
You are contradicting yourself when you implement the required tableview datasource methods (i.e. the numberOfRowsInSection and the cellForRowAtIndexPath methods)
You provide the count of cells here:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
if (section == 0)
{
return clubs.count;
}
else{
return webcourseDetails.count;
}
}
So, your cellForRowAtIndexPath method should look something like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
// cell init/dequeuing
if (indexPath.section == 0) {
cell.textLabel.text = clubs[indexPath.row]; //Assuming that is an NSString instance
} else {
cell.textLabel.text = webcourseDetails[indexPath.row]; //Assuming that is an NSString instance
}
return cell;
}
Please, try to do the following (I think you're not re-loading table after all items are read):
[itemTable readWithCompletion:^(NSArray *results, NSInteger totalCount, NSError *error) {
clubs = [results mutableCopy];
amount = totalCount;
if (error) {
NSLog(#"Error: %#", error);
} else {
//NSLog(#"Item read, id: %#", [results objectAtIndex:1]);
for (int i = 0; i < results.count; i++)
{
NSLog(#"Item read, id: %#", [results objectAtIndex:i]);
}
[YOURTABLENAMEHERE reloadData];
}
}];
Replace YOURTABLENAMEHERE with a reference to your table.

Online search in SearchBar

I trying to do an online search using searchBar, I doing next:
//-=-=-=-=Methods for search Bar=-=-=-=
-(void)searchThroughData {
self.result=nil;
//Send searched substrint ti server
if (self.searchBar.text.length > 0) {
NSString *searchParams = [NSString stringWithFormat:#"<request<user_name>%#</user_name></request>", self.searchBar.text];
[self initRequest:searchParams];
}
}
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
[self searchThroughData];
}
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSString *dataString = [[NSString alloc] initWithData:_receivedData encoding:NSUTF8StringEncoding];
// -=-=-=-=-=-=-=-=-=-=Parse the XML into a dictionary-=-=-=-=-=-=-=-=-=-=
NSError *parseError = nil;
_xmlDictionary= [XMLReader dictionaryForXMLString:dataString error:&parseError];
NSDictionary * dict=[_xmlDictionary objectForKey:#"result"];
NSDictionary *dict1 = [dict valueForKey:#"user"];
_result = [[NSMutableArray alloc] initWithArray:[[dict1 valueForKey:#"name"] valueForKey:#"text"]];
NSLog(#"res: %#", _result);
[self.tableView reloadData];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
/* !!!This never get called!!!
if (tableView == self.searchDisplayController.searchResultsTableView) {
NSLog(#"in search");
}
*/
if(!self.searchDisplayController.isActive) {
return myCategories.count;
}
else
{
NSLog(#"in search === %d", _result.count);
return _result.count;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"Cell"];
}
if (!self.searchDisplayController.isActive) {
cell.textLabel.text = myCategories[indexPath.row];
return cell;
}
else {
NSLog(#"search cllFrRwAt %#", _result[indexPath.row]);
cell.textLabel.text = _result[indexPath.row];
return cell;
}
}
I can see in console that "in search === 5", and "search cllFrRwAt john" (5 times), but on the screen I see "no result". Only if I tap Cancel button on searchBar I'm see my downloaded result. How can I show download result immediatly as data was downloaded and update searchDisplay?
EDIT:
I've changed searchThroughData method with :
-(void)searchThroughDataWithString: (NSString *)searchingStr {
…
}
and
[[NSOperationQueue mainQueue] addOperationWithBlock:^ {
NSLog(#"Main Thread Code");
[self.tableView reloadData];
}];
But this doesnt help

UITableView gets Slower with every new NSMutableArray

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.

Resources