NSUserDefaults + NSMutableArray -> Storing 2 arrays and display in tableview - iphone

I have just implementet a bookmark/favorites function in my app, favorites from a tableview, with the following code, using NSUserDefaults. The cell has 2 labels, the name of the item and a price - stored in the Arrays - theArray and thePriceArray -> like this:
NSIndexPath *indexPath = [_ListTableView indexPathForCell:(UITableViewCell *) [[sender superview] superview]];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSMutableArray *OrderList = [[defaults objectForKey:ORDER_KEY] mutableCopy];
if (!OrderList) OrderList = [NSMutableArray array];
[OrderList addObject:[theArray objectAtIndex:indexPath.row]];
[OrderList addObject:[thePriceArray objectAtIndex:indexPath.row]];
[defaults setObject:OrderList forKey:ORDER_KEY];
[defaults synchronize];
I am now adding the two arrays theArray & thePriceArray, to the NSMutableArray.I now want to show these information (the information from the arraies) in another tableview. I do this like so:
In My viewDidAppear:
NSUserDefaults *defaults = kSettings;
NSMutableArray *theOrderList = [NSMutableArray arrayWithArray:[defaults objectForKey:ORDER_KEY]];
And to show the contents in the tableview:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [theOrderList count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"TheTableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = [theOrderList objectAtIndex:indexPath.row];
return cell;
}
This is almost working as I want, the contents of theArray and thePriceArray is shown, but in a long list like so:
I want the "key and the value" to be in one cell, so the price and the item name in one cell (Hat - 30) and not seperate, how can I do that? I have tried to use a NSDictionary, but without luck and can I use NSDictionary for this?

You can create two new arrays for favItem and favPrize. Just add your favorite Items to favItem Array and add favorite Prizes to favPrize Array. Now use these arrays to set the labels and detailLabels of your Tableview like :
cell.textLabel.text = [favItems objectAtIndex:indexPath.row];
cell.detailTextLabel.text = [favPrize objectAtIndex:indexPath.row];

Keep both array theArray and thePriceArray seperate and use one as your main array for data source of tableView.
Note : add data from NSUserDefault to respective array.
Now method will be :
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [theArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"TheTableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubTile reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = [theArray objectAtIndex:indexPath.row];
cell.detailTextLabel.text = [thePriceArray objectAtIndex:indexPath.row];
return cell;
}

You can simply do it using the following code:
NSString *label = [NSString stringWithFormat:#"%# %#",[theOrderList objectAtIndex:(indexPath.row * 2)],[theOrderList objectAtIndex:(indexPath.row * 2)+1]
cell.textLabel.text = label;
And also change your numberOfRowsInSection like:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [theOrderList count]/2;
}

Related

UISearchBar, NSPredicate and NSMutableArray

Have next Table View:
image capture screen
this its make with two NSMutableArrays from Sqlite Database, sublista and subdetail, in example element 0 of sublista contain "A Barda" and element 0 of subdetail contain "Ponteceso".
This code generate this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"subCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell==nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
cell.accessoryType =UITableViewCellAccessoryDetailButton;
}
NSString *title;
cell.textLabel.text=[sublista objectAtIndex:indexPath.row];
cell.detailTextLabel.text=[subdetail objectAtIndex:indexPath.row];
return cell;
}
Need Add A UIsearch bar and create NSDictionary:
NSMutableDictionary *playas = [NSMutableDictionary dictionaryWithObjectsAndKeys:sublista, #"nombreplaya", subdetail, #"localidadplaya", nil];
But How implement Search or filter Here?
BEST REGARDS

Populating UITableView with NSArray in iOS 7

A lot of the methods have deprecated in iOS 7 in order to set font, textLabel, and color for UITableView cells. I'm also just having a difficult time populating the view with these values. Here's a snippet of my code:
- (void)fetchedData:(NSData *)responseData {
//parse out the json data
NSError* error;
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:responseData
options:kNilOptions
error:&error];
NSArray* jobs = [json objectForKey:#"results"];
for(NSDictionary *jobsInfo in jobs) {
JobInfo *jobby = [[JobInfo alloc] init];
jobby.city = jobsInfo[#"city"];
jobby.company = jobsInfo[#"company"];
jobby.url = jobsInfo[#"url"];
jobby.title = jobsInfo[#"jobtitle"];
jobby.snippet = jobsInfo[#"snippet"];
jobby.state = jobsInfo[#"state"];
jobby.time = jobsInfo[#"date"];
jobsArray = [jobsInfo objectForKey:#"results"];
}
}
I am looping through an array of dictionaries from a GET request and parsed. I am now attempting to fill my UITableView with the following code:
-
(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [jobsArray 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];
}
NSDictionary *jobsDic = [jobsArray objectAtIndex:indexPath.row];
[cell.textLabel setText:[jobsDic objectForKey:#"jobtitle"]];
return cell;
}
Also, I have declared this is in my .h file:
NSArray *jobsDic;
Any ideas on what I'm doing wrong? Is this an iOS 7 problem?
It seems that you reinitialize jobsarray at the end of the forin loop.
You didn't mean ?
NSArray* jobs = [json objectForKey:#"results"];
NSMutableArray *jobsTemp = [[NSMutableArray alloc] initWithCapacity:jobs.count];
for(NSDictionary *jobsInfo in jobs) {
JobInfo *jobby = [[JobInfo alloc] init];
jobby.city = jobsInfo[#"city"];
jobby.company = jobsInfo[#"company"];
jobby.url = jobsInfo[#"url"];
jobby.title = jobsInfo[#"jobtitle"];
jobby.snippet = jobsInfo[#"snippet"];
jobby.state = jobsInfo[#"state"];
jobby.time = jobsInfo[#"date"];
[jobsTemp addObject:jobby];
}
self.jobsArray = jobsTemp; //set #property (nonatomic, copy) NSArray *jobsArray; in the .h
[self.tableView reloadData]; //optional only if the data is loaded after the view
In the cell for row method :
- (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];
}
JobInfo *job = self.jobsArray[indexPath.row];
cell.textLabel.text = job.title;
return cell;
}
And don't forget :
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.jobsArray.count;
}
Update - an user suggested an edit :
It's true that count isn't a NSArray property. But as Objective-C lets us use a shortcut notation for calling method with a dot, this code works. You have to know limitation of this : if you use a NSArray subclass with a count property with a custom getter this could have side effects #property (nonatomic, strong, getter=myCustomCount) NSUInteger count. As I think code readability is to me one of most important things I prefer to use dot notation. I think Apple SHOULD implement count as readonly property so I use it this way (but it's my point of view). So for those which don't agree with me just read return [self.jobsArray count]; in the tableView:numberOfRowsInSection: method.
Change the declaration of jobsArray from NSArray to NSMutableArray.
Add an initialization at the beginning point of fetchedData method like follows.
if(!jobsArray) {
jobsArray = [NSMutableArray array];
}
else {
[jobsArray removeAllObjects];
}
Remove the following line.
jobsArray = [jobsInfo objectForKey:#"results"];
Instead of that, add the initialized object to the array at the end of for loop.
[jobsArray addObject:jobby];
Add a [tableView reloadData]; at the end of your *-(void)fetchedData:(NSData )responseData; method implementation.
Initially when you are loading the view, tableView will get populated. After you received the data, tableView will not be known that it is received.
Everything else seems good. Hope rest will work fine.

How to get display data in UITableView Section tables with single Array

I have data on a server which I want to show in the a tableView.
The problem is that I want to show data based on categories so I have array categories which has categories which will be section titles and inside them there data so for display the data in section I have to declare Array.
e.g. If there are three categories then we have to make three array to populate data but what if there are more categories as categories are dynamic and come from server.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [categoryArray count] ;
}
And how to set title for section title, as it is in category array, so if it is section one by one in array.
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NSLog(#"Number of Sections");
if(section == 0)
return #"Sales";
if(section == 1)
return #"Soft Skills";
}
How to show data in tableView cells may I create arrays for all the categories?
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (section==0)
{
appDelegate = (MultipleDetailViewsWithNavigatorAppDelegate *)[[UIApplication sharedApplication] delegate];
int count=[resultArray count];
NSLog(#"resultArry Row Counts is %d",count);
return [resultArray count];
}
else{
appDelegate = (MultipleDetailViewsWithNavigatorAppDelegate *)[[UIApplication sharedApplication] delegate];
int count=[resultArrayOne count];
NSLog(#"resultArry Row Counts is %d",count);
return [resultArrayOne count];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Table Cell Data");
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
if (indexPath.section==0) {
appDelegate = (MultipleDetailViewsWithNavigatorAppDelegate *)[[UIApplication sharedApplication] delegate];
ObjectData *theCellData = [resultArray objectAtIndex:indexPath.row];
NSString *cellValue =theCellData.sub_Category;
cell.font=[UIFont fontWithName:#"Helvetical Bold" size:14];
NSLog(#"Cell Values %#",cellValue);
cell.textLabel.text = cellValue;
return cell;
}
else {
appDelegate = (MultipleDetailViewsWithNavigatorAppDelegate *)[[UIApplication sharedApplication] delegate];
ObjectData *theCellData = [resultArrayOne objectAtIndex:indexPath.row];
NSString *cellValue =theCellData.sub_Category;
cell.font=[UIFont fontWithName:#"Helvetical Bold" size:14];
NSLog(#"Cell Values %#",cellValue);
cell.textLabel.text = cellValue;
return cell;
}
}
Since getting the categories from the server does not seem to be your question I base my answer on pre filled arrays for a better visualization.
NSMutableArray *categories = #[#"Cat1", #"Cat2"];
// creata a dictionary with all the array for the categorie rows
NSMutableDictionary *rowDict = #{#"Cat1":#[#"Cat1Row1",#"Cat1Row2",#"..."],
#"Cat2":#[#"Cat2Row1", #"Cat2Row2",#"..."]
Key to this solution is that you use the category string as key for the dictionary.
You can now access the title like this
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return categories[section];
}
And access your rows like this
- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// ...
// create or deque a cell like you normally would do
// now configure the cell
cell.textLable.text = [rowDict[categories[indexPath.section]] objectAtIndex:indexPath.row]
}
use
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [categoryArray objectAtindex:section];
}
for section title.
likewise, store the values for each categories in a nsmutable array NSDictionary and display the data for each category in uitableviewcell.
Try the below code. It'll solve your problem :
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [categoryArray objectAtIndex:section];
}
EDIT :
First Create a model data class to store data of your categories.
Use this model class to feel your numberOfRowsInSection and cellForRowAtIndexPath delegate function.
Instead of creating different-different array for each category. Store this array in one model class. It'll be easy to handle.

Xcode table view from array splitted

I'm trying to get a tableview starting from a string in this format "name1,link1,name2,link2..."
So what i'm actually doing is this:
-Get the string and put links and names into an array, then split the array into two lesser ones by the position of the objects
- (void)viewDidLoad
{
NSString *dataString = #"a,www.google.it,b,www.apple.it,c,www.youtube.it";
dataArray = [dataString componentsSeparatedByString:#","];
for (int i=0; i<[dataArray count]; i++) {
if (i%2==0) {
[dataArrayName addObject:[dataArray objectAtIndex:i]];
}
else {
[dataArrayLink addObject:[dataArray objectAtIndex:i]];
}
}
[super viewDidLoad];
}
-Set up the table view
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
{
return [dataArrayName count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdentifier = #"myCell";
// Try to retrieve from the table view a now-unused cell with the given identifier.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
// If no cell is available, create a new one using the given identifier.
if (cell == nil) {
// Use the default cell style.
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"myCell"];
}
// Set up the cell.
NSString *cellName = [dataArrayName objectAtIndex:indexPath.row];
cell.textLabel.text = cellName;
return cell;
}
But when i run the application the view with the tableview is clear (there are empty rows)
What's the problem?
Have you initialized dataArrayName and dataArrayLink (ie, at some point, before you started adding objects to it, did you say dataArrayName = [[NSMutableArray alloc] init] or an equivalent?

Modify multiple rows on uitableview on view load

I have a UITableView that should have 33 rows. Each row represents a specific time slot in a day. When the view that holds the table view loads, I need it to populate each row accordingly.
I have an array of reservation objects that gets passed to the view. Each reservation contains a slot number, a reservation name and the duration of the reservation in slots.
What is the best way to populate the table, I am currently iterating through the array of reservations in the - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath method.
This is not giving me the results or the behavior I am expecting. The performance is extremly poor as it keeps iterating through loops and cells that shouldn't be blue are blue after scrolling. What is the best way to approach this? I have included the code below.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 33;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
NSString *timeStamp = [NSString stringWithFormat:#"%.2f", (indexPath.row + 14.0 ) / 2.0];
timeStamp = [timeStamp stringByReplacingOccurrencesOfString:#".50" withString:#":30"];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [NSString stringWithFormat:#"%#: ", timeStamp];
for (Reservation *temp in bookingsArray) {
if ((temp.slotNumber - 1) == indexPath.row) {
cell.textLabel.text = [NSString stringWithFormat:#"%#: %#", timeStamp, temp.reservationName];
cell.contentView.backgroundColor = [UIColor blueColor];
}
for (NSNumber *tempNo in temp.slotIdentifiers) {
if ([tempNo intValue] -1 == indexPath.row) {
//cell.textLabel.text = [NSString stringWithFormat:#"%#: Booked", timeStamp];
cell.contentView.backgroundColor = [UIColor blueColor];
}
}
}
return cell;
}
UPDATE
Trying the following gives me strange behaviour where all the cells turn blue after I start scrolling.
- (void)viewDidLoad
{
[super viewDidLoad];
bookManager = appDelegate.bookingManager;
bookingsArray = [[NSArray alloc] initWithArray:[bookManager getBookingsForCourt:1 onDate:[NSDate date]]];
namesArray = [[NSMutableDictionary alloc] init];
slotIndexSet = [NSMutableIndexSet indexSet];
for (int c = 0; c < 33; c++) {
[namesArray setObject:#"Available" forKey:[NSNumber numberWithInt:c]];
}
for (Reservation *temp in bookingsArray) {
[namesArray setObject:temp.reservationName forKey:[NSNumber numberWithInt:temp.slotNumber]];
for (NSNumber *slotNo in temp.slotIdentifiers) {
[slotIndexSet addIndex:[slotNo intValue] + 1];
}
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
NSString *timeStamp = [NSString stringWithFormat:#"%.2f", (indexPath.row + 14.0 ) / 2.0];
timeStamp = [timeStamp stringByReplacingOccurrencesOfString:#".50" withString:#":30"];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [NSString stringWithFormat:#"%#: ", timeStamp];
cell.textLabel.text = [namesArray objectForKey:[NSNumber numberWithInt:indexPath.row]];
if ([slotIndexSet containsIndex:indexPath.row]) {
cell.contentView.backgroundColor = [UIColor blueColor];
}
return cell;
}
You need to do two things to speed this up:
Convert bookingsArray to a bookingBySlotNumber array in such a way that the object at index i has slotNumber - 1 equal to i. You can do it by iterating over the original bookings array when you receive it.
Create a NSIndexSet called isBookedBySlotNumber containing indexes of items that have been booked. You can prepare it by going through all Reservation.slotIdentifiers, and marking the indexes of isBookedBySlotNumber for items that have been booked.
With these two pre-processed items in place, you can eliminate the nested loops altogether: the outer one will be replaced by a lookup in bookingBySlotNumber, and the inner one - by a loopup in isBookedBySlotNumber.