I have a UIScrollView that contains a UIImageView and a UISearchDisplayController. When the user taps on the image, the search display controller appears. I’m filtering a list based on the search text and the table associated with the UISearchDisplayController is correctly updated. When the user taps on an row in the table, I am receiving the didSelectRowAtIndexPath. That’s what is working. (I used this tutorial to help me implement the UISearchDisplayController.)
However, I can’t figure out how to (a) remove the UISearchDisplayController (i.e., the search box and table) from within didSelectRowAtIndexPath and (b) how to pass information about the row that was selected to the UIScrollView.
Thanks.
A) You should be able to dismiss the UISearchDisplay Controller with something like:
[searchDisplayController setActive:NO animated:YES];
B) I am assuming you are launching a new view controller to display information about the row selected? If so, do something like this:
MyViewController *viewController = [[MyViewController alloc] initWithNibName:#"myNibName" bundle:nil];
MyObject *object = [allObjects objectAtIndex:indexPath.row];
// pass object to view controller's "object" property
viewController.object = object;
[self.navigationController pushViewController:viewController animated:YES];
Sorry if anything is out of syntax, didn't type into xcode.
Related
My setup is using a storyboard in which I create a login, then a home screen in which the user can press a button to display their messages.
These are displayed in a table which is instantiated programmatically.
From this table I then want to press a row to go into detail about that row, but when i do this the view displayed is blank but all methods associated with the class are being fired (view did load, and so on).
I have literally tried 10 different ways from different solutions others had had suggested on their questions but nothing works.
Code to make new view and push it:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
messageDetail *messageDetailView = [[messageDetail alloc]initWithNibName:nil bundle:nil];
messageDetailView.message = [entityObjects objectAtIndex:indexPath.row];
[self.navigationController pushViewController:messageDetailView animated:YES];
}
ViewDidLoad of DetailView:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
NSLog(#"Message Detail:\n%#",message);
messageTitle.text = message.message_title;
messageBody.text = message.message_xml;
}
I have tried using a segueIdentifier route and then intercepting the prepareSegue: to add data to the new view, but as the tableView is created programmatically there is no segue.
I have tried instantiating the view from storyboard via:
messageDetailView = [self.storyboard instantiateViewControllerWithIdentifier:#"MDV"];
But the app crashes as there is no view with identifier, even though i set the identifiers.
You send nil as nib name, if you do not have a nib file do not allocate the message detail view with initWithNibName function.
Use raw init or initWithFrame. Whichever works for you.
Good luck
I basically did the same thing with this code here. Hope this helps
Detail_View *next=[[Detail_View alloc] initWithNibName:#"Detail_View" bundle:nil];
//These are just values that I needed to set before going to the next page.
//You can use this if you want to pass over the value of your table row
//otherwise ignore this
next.htmlContents= [[storage_array objectAtIndex:indexPath.row]objectForKey:#"title"];
next.titleText=[[storage_array objectAtIndex:indexPath.row] objectForKey:#"title"];
[self.navigationController pushViewController:next animated:YES];
There are actually three views at play. My homeView, which is where I launch the picker from, which sets the StudyPickerController view as root to a navController, which is then presented inside of the popOverController. Then from within the StudyPickerController view, I need to push to the ScreenPickerController, a different view completely.
I have a UIPopOverController that is displaying the contents of a view that is a tableView. I would like to be able to push a new view with a viewController inside of this view, but as I will discuss, it is really close, but it just won't push!
So from my homeView, when the button is pushed, an action is called and this code is run:
self.studyPicker = [[[StudyPickerController alloc] initWithStudyArray:self.studyArray ViewNum:butto.tag] autorelease];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:self.studyPicker];
_studyPicker.delegate = self;
self.studyPickerPopover = [[[UIPopoverController alloc] initWithContentViewController:navController] autorelease];
[self.studyPickerPopover presentPopoverFromRect:CGRectMake(120,45, 10,10) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
And this works pretty well! The popOverController displays the contents of my StudyPickerController without any problems. I get the feeling that I am indeed getting access to my navigationController because the frame of the popOverController has a bar at the top, instead of just being a thin border, it has a navigationBar.
So now when I want to select a row in this view, I would like to push to a new view, also with a tableView, with my navigationController. This is the code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSArray * array = [_studyArray objectAtIndex:indexPath.row];
ScreenPickerController * picker = [[ScreenPickerController alloc] init];
picker.seriesGUID = array;
picker.viewNumber = viewNumber;
[self.navigationController pushViewController:picker animated:YES];
}
It seems to me that this should be working! But alas, I press a row, and it highlights, and nothing happens.
I've been working on this all day, so it very well could be that I am just missing something, but I don't know what it is. Any help is appreciated
It seems there are two classes involved here: your homeView class and the StudyPickerController. I'm guessing the tableView:didSelectRowAtIndexPath: method would be in the homeView class?
In that case, self.navigationController is trying to access the navigation controller that homeView is in, not the navigation controller you put into the popover. Since homeView isn't even in a navigation controller, the accessor returns nil.
Instead, you will want to use something like [self.studyPicker.navigationController pushViewController:picker animated:YES];.
im my app that im tring to build, i want to have a table view, where you select a row e.g email address. the view pushes to a simple page with a uitextField, when you hit the save button it pops the view controller back to the initial page, where the user can select the next field.
the issue that i am having is passing the information entered in the textfile back to the first view controller. this should be really simple, but anything i try just does not work
what is the best way to go around this.
thanks
You are probably thinking about the problem backwards. In an MVC system like Cocoa, the job of View Controllers is to manage views, not data. Create a model object to hold the data you're updating. When you create a view controller, pass the model object to it. It may update the model with changes the user makes. It should not worry about who called it, or who it returns to. It should just update the model object, and other interested parties should read the model object. As an example:
SettingsViewController would have a model object called Settings
When you dive into a detail view controller like EmailViewController, you pass the settings to it like emailViewController.settings = self.settings before presenting it.
When the user makes changes, just update the object like self.settings.emailAddress = ...
This separates your view logic from your model logic, which is a key features of Cocoa patterns. If you fight this pattern, you're going to often find yourself thinking "it sure is hard to get there from here."
You can either use a delegate method or, even simpler, just define an instance variable NSString *textEntry in the first view controller that can be set (property/synthesize) and then access that view controller from the stack.
For example, in the pushed view, do something like:
FirstViewController *firstViewController = [[[self navigationController] viewControllers] objectAtIndex:0];
[firstViewController setTextEntry:[textfield text]];
The easiest way I found to do this is using NSNotificationCenter.
In the ViewController with the TableView:
- (void)updateRowValue:(NSNotification *)notification{
NSDictionary *valuesDictionary = [[NSDictionary alloc] initWithDictionary: [notification userInfo] copyItems:NO];
NSString *newString = [valuesDictionary objectForKey:#"StringVal"]
}
This is the method called when row is selected
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
TextFieldViewController *tfvc = [[TextFieldViewController alloc] init];
[tfvc setPostNotificationString:#"updateRowValue"];
[self.navigationController pushViewController:tfvc animated:YES];
}
Now in the viewController with the textField, when you press the button to return to the previous viewController call this:
- (IBAction)saveButtonPressed{
NSArray *valuesArray = [[NSArray alloc] initWithObjects:textField.text,nil];
NSArray *keyArray = [[NSArray alloc] initWithObjects:#"StringVal",nil];
NSDictionary *dictionary = [[[NSDictionary alloc] initWithObjects:valuesArray forKeys:keyArray] autorelease];
[[NSNotificationCenter defaultCenter] postNotificationName:[self postNotificationString] object:self userInfo:dictionary];
[[self navigationController] popViewControllerAnimated:YES];
}
I have three objects in the applicaion. There is a UItableviewcontroller(with nib file) that shows a list of the items. One UIviewcontroller to add item (with nib file) and a model class that contains item object.
I show the list of item firstly (on application start). I have a navigation button on navigation bar to pop up add view (add as subview) on the same screen (on table view). In add view I have a add button. when I click on add button it adds the record and disappear from the table view but doesn't reload the that.
I have used following code in add item button click action
listitem *home= [[listitem alloc] initWithNibName:#"listitem" bundle:nil];
[self.navigationController pushViewController:home animated:YES];
[home viewWillAppear:YES];
[home release];
[self.view removeFromSuperview];
In viewwillappear function I am reloading the data from database and also reloading the table view data using reloadData.
Am I doing correct. What is the mistake I am doing.
Your code is very tricky to read* but this is what I think you're doing:
You're making a new list each time that you add an item. you don't want to create a new home object, you want to go back to the last one?
i.e. replace your code with
[self.navigationController popViewControllerAnimated:YES];
and this will go back to your original list, which should have refreshed itself (a UINavigationController will call viewWillAppear for you).
Hope that helps.
NB You have to have used a navigation controller to add your 'add item' view otherwise this code won't work :( This is how you should be adding your item view.
AddItem *home = [[AddItem alloc] initWithNibName:#"AddItem" bundle:nil];
[self.navigationController pushViewController:home animated:YES];
This will slide on your add item view.
If you want the add item view to be a popup, a UINavigationController is definitely not the way to do it!
You will need to tell your initial list view when it needs to update itself. You can do this using either a delegate or a notification. I'd go for a delegate in this case.
You need to add this to your add item view controller's code (AddItem's .h file)
#interface AddItem : UIViewController {
UITableViewController *delegate;
}
#property (nonatomic, assign) UITableViewController *delegate;
#end
and synthesize it in your AddItem's .m file
#synthesize delegate;
When you create your add item view controller, set the delegate to be the initial view controller. i.e.
AddItem *home= [[AddItem alloc] initWithNibName:#"AddItem" bundle:nil];
home.delegate = self;
home.view.frame = CGRectMake(10, 20, 300, 300);
[self.view addSubview:home.view];
Finally, when you have added a new item, tell your delegate to refresh itself like so :
[delegate reloadData];
[self.view removeFromSuperview];
*It's standard practice to use capital letters for class names i.e. listitem should be called ListItem. Personally, I'd call it ItemListViewController so it's clear what it does.
I am having a problem with a table and showing another view when the user touches a table cell. I am using a UITabBarController for the main view to show different views. I then use a UINavigationController when the user selects a UITableView view to display the next view from the table cell selection.
My problem is this: when they select the table cell, the cell is highlighted and the next view does not appear. I am using IB. All of the examples I have found are doing this the same way I am, except the examples work!
I have the controllers loaded in a NSMutableArray with a Dictionary. I also tried this code by directly creating a view controller rather than using the array item. Same results....
I checked the target controller (Calc1ViewController) to make sure there was nothing wrong with the controller. When showing it directly, the controller (Calc1ViewController) displays correctly.
Here is some code.....
The initialization of the view controller in the dictionary:
Calc1ViewController *calc1ViewController = [[Calc1ViewController alloc] init];
[menuList addObject:[NSDictionary dictionaryWithObjectsAndKeys:
NSLocalizedString(#"SSC - page 1",#""), #"title",
calc1ViewController, #"viewController",
nil]];
[calc1ViewController release];
I also tried this without using the dictionary -- creating a view controller in place of the [[menuList objectAtIndex:...]; line -- by creating the view controller like this:
Calc1ViewController *targetViewController = [[Calc1ViewController alloc] init];
// the table's selection has changed, switch to that item's UIViewController
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UIViewController *targetViewController = [[menuList objectAtIndex: indexPath.row] objectForKey:#"viewController"];
[[self navigationController] pushViewController:targetViewController animated:YES];
targetViewController = nil;
}
The navigation controller is defined in the AppDelegate and connected to the RootViewController through IB.
When I select a table row, it shows in the debugger that the pushViewController code is executed, but the next view does not show. Here is an example:
alt text http://thecoolestcompany.com/ssc-table-view.jpg
Any ideas?
Finally figured it out......
I had the UINavigationController and the UITabBarController on the same level. After moving the Navigation Controller as a child to the tab bar controller, everything worked. You may add as many navigation controllers to a tab bar as you would like. In IB is is a little confusing. You need to drag the NavigationController into the TabBar to as it as a new Tab Bar item.
Theres not much to go by with t he code you have provided. Only thing i can think of without looking at more code is that perhaps you have not initialized your view controller (the one in your dictionary) correctly, or at all, or the dictionary you are accesing there is not the correct one...
What is the value of [self navigationController] when pushViewController is called. Is it nil?
What is the value of targetViewController when it is passed to pushViewController. Is it nil?