I have an iPhone application that reads the details of local businesses from a .csv file. There are 3 main section:
Where to Sleep
Where to Eat
What to Do
Depending on which one is clicked (e.g. Where to Sleep), you get a sub section of options like:
B&B
Hotels
Caravan and Camping
Then if you select e.g. Hotels, you are shown a UITableView of the list of hotels. The UITableView has 2 sections in it to differentiate between 3 Star and 4 Star hotels. See screen grab below.
This is all OK so far but when I click on a cell to segue to the business' details page (a UIViewController), I segue with the wrong cell information.
I have stepped throughout the code in my UITableViewController's didSelectRowAtIndexPath and it would seem that I am registering the correct selection on each cell.
As an example, in the image above, if I select Ballyroe Heights Hotel, this is the output I get when stepping through it. Where dataArray() is an NSMutableArray that holds an NSMutableArray of 3 Star and an NSMutableArray of 4 Star Hotels that are added as below.
[dataArray addObject:threeStarArray];
[dataArray addObject:fourStarArray];
However, clicking on Ballyroe Heights Hotel displays the details for Ballygarry House Hotel and Spa
A clue to what may be going on is in the Shopping section. Below is a screen grab of what the Shopping view and sections look like.
Clicking on Manor West Retail Park display the correct information. But clicking on Shaws Department Store displays Manor West Retail Park again. Then clicking on Thats Perfect displays Shaws Department Store - and clicking on Sean Hussey displays Thats Perfect details. This is repeated for each section.
Clicking on Hardware (Kellihers...) stars the display again at Manor West Retail Park.
But again stepping through it, it seems that the correct cell is chosen in didSelectRowAtIndexPath().
In the example below I have selected Sean Hussey and again the output shows that the correct cell was chosen and that the segue sender:selectedCell is the Sean Hussey object.
However, the object that is passed to the UIViewController is of Thats Perfect.
Can anyone see where I am going wrong? Additional code can be supplied but Im sure the issue has to lie here as this method checks for row selections and performs the segues.
You are using wrong API to send data. Data is passed using prepareForSegue not performSegue
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"mySegueId" sender:self];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSLog(#"prepareForSegue: %#", segue.identifier );
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
if ([segue.identifier isEqualToString:#"mySegueId"] && indexPath)
{
NSArray *selectedRowArray = [dataArray objectAtIndex:indexpath.section];
BusinessDetailContent *selectedContent = [selectedRowArray objectAtIndex:indexpath.row];
BusinessDetailController *detailController = segue.destinationViewController;
detailController.selectedcontent = selectedContent;
}
}
Related
I am brand new to iOS programming and am currently taking an iOS class at school. For a project that I am doing we have to write a basic master-detail application for iPhone. For my app, I am creating a simple to do list type of app. The name of each task is displayed in the master view, the name of the task can be changed in the detail view. I set up a save button that has an unwind segue delegate when pressed. When i press the button I segue back to the master view I cannot get the value of the corresponding cell to change in real time. I know that it the master view is getting the changed information back because the changed information doesn't get saved until control transfers back to the master view and it is getting saved. When I rerun the app, the new name is displayed instead of the default name.
here is the delegate for the unwind segue
- (IBAction) done:(UIStoryboardSegue *)segue
{
// index for the cell in the master view table that was changed
NSIndexPath *changeIndex = [self.tableView indexPathForSelectedRow];
[self tableView:self.tableView cellForRowAtIndexPath:changeIndex];
// place the new dictionary entry created by the detail view in the location of the
// array where the old entry was located
_taskList[changeIndex.row] = self.ChangedEntry;
// store the change in the plist file
[_taskList writeToFile:self->documentPlistPath atomically:YES];
}
which calls this function, which appears to change the text for a cell in a table but I'm not sure
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.textLabel.text = _taskList[indexPath.row][TASK_DATA_NAME];
return cell;
}
So yeah, I am just trying to figure out how to make the master view reflect changes made in the detail view without having to close the app and reopen it. Oh and I am using Xcode 5 and targeting iOS 7.
Basically, after you update your data model (_taskList) you need to refresh the table view by calling reloadData on it. This tells it to update all of the rows.
I've got a basic restaurant menu system for the iPad using storyboards, and I have a product view with a button to add the item to the order page, how can I get it so that when the user presses the add to order button it adds the product name to the order scene. I've thought about using a table view in the order page but I don't know if that was a good idea. Mainly I just need some help on how to get it to print the corresponding product name onto the order page when the button is pressed. Any ideas?
Thanks,
Aislinn
how can I get it so that when the user presses the add to order button it adds the product name to the order scene.
You're mixing up presentation and data, which is a bad idea. Create a representation of orders that has no view logic at all. When a button is pressed to add something to an order, the view controller should tell the class that manages orders to do so. When you need to display an order, the view controller should ask the class for the details. For more information, read up on the MVC design pattern, which Apple uses heavily.
Just add the product name to an NSMutableArray and have the tableview load the items from this array and display it to the user.
Edit:
When the user clicks the button to add the product, use [arrayName addObject:#"Product Name"]. Then, to load it in the tableview, use the tableview's delegate method - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{} to load the name into the cell. Something like this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *identity = #"MainCell";
UITableViewCell *cell;
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identity] autorelease];
cell.textLabel.text = [arrayName objectAtIndex:indexPath.row];
return cell;
}
I have following problem.
I have created a tab based Application with three Views and Viewcontroller.
FirstView(Start screen stuff), SecondView (Detailpage), ThirdView (Table for listing items).
(Connections from storyboard were set automatically).
In the third view a table is integrated and the content is displayed fine.
Now I would like to call the SecondView , when a row in the table is selected.
I also tried to add a forth View , outside the tabBar Controller, to get the Detailview, but this also did not help.
I have tried several tutorials and forum tips, but cannot get it working.
The class is set to the right ViewController, the identifier is set to detail.
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
DetailViewController *detail = [self.storyboard instantiateViewControllerWithIdentifier:#"detail"];
[self.navigationController pushViewController:detail animated:YES];
detail.label1.text = #"It is working";
}
When clicking on the row, it becomes blue, but nothing happens. No error Message , nothing.
Hope that you can help :-)
OK, I have tried to "optimize" my design.
Still have the tab based Views, but when clicking on a row in the table, a new (not linked in Storyboard) view should appear to display the details of the selected quote.
I have created a view in the storyboard and called it "detailzitat"
I have created a DetailViewController.h/m as UIViewcontroller class
I have set the custom class to DetailViewController
I import the DetailViewController.h in the ThirdViewController.h
I have modified the didSelectRowAtIndexPath method in ThirdViewController.h accordingly.
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
DetailViewController *detailVC = [self.storyboard instantiateViewControllerWithIdentifier:#"detailzitat"];
[self.navigationController pushViewController:detailVC animated:YES];
}
and my DetailViewController.m looks like
#import "DetailViewController.h"
#implementation DetailViewController
#synthesize label1, labeltext;
- (void)viewDidLoad
{
[super viewDidLoad];
labeltext=#"JUHU";
label1.text=labeltext;
}
But again, nothing happens, besides the row gets blue.
I do not understand. If I am using this code in a Non-Storyboard project, it is working.
What am I doing wrong ? Is there any tutorial for this combination within Storyboards ? Have not found one for this approach yet.
Try to learn from the different tutorials on the web, but the biggest problem is, most ones are not for iOS5 and I am not so good to transfer then.
Hope to get some hints :-)
You might want to think about your design. If I am understanding your description correctly, the user will be on the third tab, tap on a row in a table, and then you will be switching them back to the second tab. A navigation controller might be a more natural, less confusing, choice there.
But in any case, something like this will work sometimes:
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
DetailViewController *detailVC = [self.tabBarController.viewControllers objectAtIndex:1];
detailVC.label1.text = #"It is working"; // <- this will not work consistently!
self.tabBarController.selectedViewController = detailVC;
}
The problem with this is that while the user is on that third tab, it's possible that the second tab view controller's view is unloaded (due to memory pressure for example).
It's also possible the user went from tab 1 to tab 3 immediately and therefore the 2nd tab's view isn't even loaded yet at all. (To even test the above code you would have to select tab 2 and then tab 3.)
If the second tab's view hierarchy is not loaded, the label1 property will be nil, and so this will not work. A better strategy would be to create a new #property of type NSString* on the DetailViewController. And set that property instead of trying to set the label1 directly.
Then in your viewWillAppear: for the DetailViewController you can update your labels as needed. At that point of course you can be sure that label1 is loaded and connected to the correct UILabel.
I hope that helps.
I think problem is at self.navigationController. If your view is not inside the navigation controller this will not work. So what you do is create a new navigation controller object there and then use it to show your detail view.
Hi
I've got simple question which I don't know how to answer.
In my app I've got UITableViewController with cells. When I select one item (cell) it's getting higlighted and in other thread I'm loading chunk of data to display to the user (after load is done new VC is pushed). When doing it with thread user still can interact with application like, going back to other NavController and I do want that to happen. What I don't want to happen is that when loading isn't complete user can select other cell in table and it get's highlted. How I can prevent that (only highlit, I'm checking if there was a previous request so I'm not putting another thread untli previous request is done).
So basicly my question is, how can you foribd user from interacting with table view controller?
Set the selectionStyle of the UITableViewCell's to UITableViewCellSelectionStyleNone.
You can use the following to check if row can be selected:
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (rowSelected) {
return nil;
}
return indexPath;
}
So, you only select it if no row is selected. In your didSelectRowAtIndexPath method:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
rowSelected = YES;
// call method that is going to do something and mark rowSelected = NO;
}
You can deselect the row by using
[[tableView cellForRowAtIndexPath:indexPath] setSelected:NO animated:YES];
There is a risk that your users will be confused. A highlight is not enough. There should be very clear visual feedback that a network opperation is ongoing and that different rules apply.
either push the details view immediately after the user selected a row and show an activity indicator in there.
or give the whole table view a different look while loading data for the selected row: e.g. Show activity indicator in the selected row & hide the disclosure chevrons in all the other. While doing that, you can set the selection style to 'none'
I write an App that shows all it's information in a UITableView.
Now I use the UIViewController to show 2 UITableViews inside of it.
The first UITableView shows the primary information ( this works fine ).
But now I want to show an advertisement in my App.
I decided to use a second UITableViewController with just one UITableViewCell, which isn't scrollable. ( this second UITableViewController is shown and useable )
The very big question for me is how can I show advertisements there?
I like to show something like a video which I could make with Adobe CS4.
The phone doesn't like Flash, so which format could I use and how can I play it in an UITableViewCell?
Or, when it's better to show it in an UIView or something else, let me know.
Greetz
Wissensdurst
There's an inbuilt ad banner class, and they're also launching a video ad service early next year. Or you could override UITableViewCell to include a video player in it which could play your ad.
Why do you want to use a second TableView Controller? Just us the same and check for the indexPath.row or indexPath.section in you UITableView Delegate Methods. For instance:
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0) {
//show specific informations
}else if(indexPath.row > 0){
//show comercial
}else{
//show all other rows
}
}
or another thing you can use are the tableHeaderView or the tableFooterView. Those views are imageViews so you just can do e.g.
self.tableView.tableFooterView = (UIImageView*)myImageViewWithCommercialBanner;
For you videos, flash is definitely a no go on iphone. Use the required formats in the Apple Documentations and you are fine. For example *.m4v is a commonly used format for this.