I am trying to get a UITableView to show up after I tap a next button, I can't get it to work...
I don't know why TimesViewController.m isn't working, how do I link it...
-(IBAction)nextView:(UIBarButtonItem *) sender{
[self pushViewController:TimesTableViewController.m animated:YES];
}
You need to read through View Controller programming guide. Essentially, it depends more on your application design. The most common ways of doing this are:
Tap on nextView should present TableView controller modally.
Tap on nextView should push TableView controller in the navigation stack.
With either of the approach, you need to create a separate view controller for your table view which will manage the table view and act as delegate/data source for it.
From within your button action handler you need to do it this way:
-(IBAction)nextView:(UIBarButtonItem *) sender{
MyTableViewController *tableController = [[MyTableViewController alloc] init];
// For #1 above
[self presentViewController:tableController animated:YES completion:^{
// Any code that you want to execute once modal presentation is done
}];
// For #2 above
[self.navigationController pushViewController:tableController animated:YES];
}
EDIT:
Create a initialize method on your MyTableViewController and pass the values while calling it.
- (id)initWithData1:(NSString *)iData1 data2:(NSString *)iData2 {
if ((self = [super init])) {
self.data1 = iData1;
self.data2 = iData2;
}
return self;
}
MyTableViewController *tableController = [[MyTableViewController alloc] initWithData1:#"Some String" data2:#"Another string"];
PS: You could also expose the string property in your header file of MyTableViewController and set it from the callee class
or if you wanna do it programmatically, in your viewDidLoad, after you created your button
[firstsessionButton addTarget:self action:#selector(showtable:) forControlEvents:UIControlEventTouchUpInside];
-(void)showtable:(UIButton *)sender{
TableViewController *tableViewController=[[TableViewController alloc]init];
[self.navigationController pushViewController:tableViewController animated:YES];
}
Related
I'm trying to populate UITextFields inside a UITableViewController with a click of a cell. So, I created an init method like:
- (id)initWithObjetoFormulario:(ObjetoFormularioGerenciador *)umObjeto
{
self = [super init];
if(self){
self.objetoFormulario = umObjeto;
}
return self;
}
In my ViewDidLoad I put the line if(self.objetoFormulario){ and after that link the UITextFields to my Object. I don't think there's anything wrong at this point.
So, my Second TableViewController is a SearchDisplayController, it finds the Data I need and at didSelectRowAtIndexPath I have:
ObjetoFormularioGerenciador *objeto = [[ObjetoFormularioGerenciador alloc] init];
[objeto RecebeArrayComDadosECriaObjetoFormularioGerenciador:_arrayComDados eEmail: [searchResults objectAtIndex:indexPath.row]];
GerenciarSeriesTableViewController *gerenciador = [[GerenciarSeriesTableViewController alloc] initWithObjetoFormulario:objeto];
[self.navigationController pushViewController:gerenciador animated:NO];
As I don't have the actual objects in my cells, I call a method to retrieve the object according to the cell entry, that is working as well, now, it opens a blank TableView when I click the cell. It should go Back to my tableView with static Cells containing UITextFields and populate them.
When I use this code:
ObjetoFormularioGerenciador *objeto = [[ObjetoFormularioGerenciador alloc] init];
[objeto RecebeArrayComDadosECriaObjetoFormularioGerenciador:_arrayComDados eEmail:[searchResults objectAtIndex:indexPath.row]];
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
GerenciarSeriesTableViewController *gerenciador = [sb instantiateViewControllerWithIdentifier:#"GerenciarSeriesTableViewController"];
[self.navigationController pushViewController:gerenciador animated:NO];
It does open the TableView I want, but it doesn't populate the UITextFields as I didn't pass any object.
Thanks.
Yes, you really don't generally have custom init methods for view controllers, but rather rely upon the standard ones, and then once the view controller has been instantiated, you'd just set the property then, e.g.:
ObjetoFormularioGerenciador *objeto = ... // create and configure objeto
GerenciarSeriesTableViewController *gerenciador = [self.storyboard instantiateViewControllerWithIdentifier:#"GerenciarSeriesTableViewController"];
gerenciador.objetoFormulario = objeto;
[self.navigationController pushViewController:gerenciador animated:NO];
You can also have a segue between the two view controllers, give it an identifier, and then call [self performSegueWithIdentifier:...], and then set the objetoFormulario in the prepareForSegue method. But the above technique should work fine, too.
I am working on an iOS application where I have two separate buttons that call, and display a UIViewController from an .xib file. When this viewController is displayed for the user, the user enters data, and then dismisses the viewController, and is taken back to the main application where he/she originally came from.
My problem is that this viewController that is called, and then dismissed by the user is activated by two different buttons, and the data that is entered by the user has to be kept track based on which button calls it. However, in creating and calling the viewController, I don't know how to pass the tag value from the buttons which would distinguish which button is calling it.
Here is my code which creates and calls the viewController from the .xib file (and is called by both buttons):
- (IBAction)buttonClicked:(id)sender {
_nextView = [[NextViewController alloc] initWithNibName:#"NextViewController" bundle:nil];
[_nextView setDelegate:(id)self];
NextNavigationController *navigationController = [[NextNavigationController alloc] initWithRootViewController:_nextView];
[self presentViewController:navigationController animated:YES completion:nil];
}
This code works fine in calling the viewController, but I also need to pass with it the tag value from the button which calls this method. How can I do this?
- (IBAction)buttonClicked:(UIButton *)sender {
_nextView = [[NextViewController alloc] initWithNibName:#"NextViewController" bundle:nil];
[_nextView setDelegate:(id)self];
_nextView.buttonTag = sender.tag;
NextNavigationController *navigationController = [[NextNavigationController alloc] initWithRootViewController:_nextView];
[self presentViewController:navigationController animated:YES completion:nil];
}
buttonTag would be an integer property you create in _nextView
You can access the tag value from the sender itself
NSInteger tag = [(UIButton *)sender tag];
Regards
I have not tested this but can't you cast the sender object to a uicontrol and then get the tag ?
UIControl *view=(UIControl *)sender;
NSInteger tagNo=view.tag;
sender is a reference to the button. Just change the type of the sender to (UIButton*) and you should be able to check for the tag you want
- (IBAction)buttonClicked:(UIButton*)sender {
NSInteger tag = sender.tag;
(...)
}
I am trying to figure out for a while now, how should I use the annotation button to switch
to another mapView. The app I am working on uses MapBox - maps. I checked the exemples
provided by them, but programmatically switching between two maps is there always achieved
through tab bar (which is not the case I want to use).
I am working with storyboards and I understood it quit well, how the segue should be made
in the Interface builder, but I think I am not managing with the programmatically integrated
buttons on map views. I initiated 'id's in both header files and I proclaimed them in the
Identity Inspector as well.
This is the part of the code, where I implement the RMMMapView with the annotation in the
main View Controller - ViewController and it works perfectly:
- (void)viewDidLoad{
[super viewDidLoad];
RMMapBoxSource *onlineSource = [[RMMapBoxSource alloc] initWithMapID:(([[UIScreen mainScreen] scale] > 1.0) ? kRetinaMapID : kNormalMapID)];
_mapView = [[RMMapView alloc] initWithFrame:self.view.bounds andTilesource:onlineSource];
_mapView.tileSource = [[RMMapBoxSource alloc] initWithMapID:(([[UIScreen mainScreen] scale] > 1.0) ? kRetinaMapID : kNormalMapID)];
_mapView.centerCoordinate = CLLocationCoordinate2DMake(0,0);
_mapView.adjustTilesForRetinaDisplay = YES;
_mapView.zoom = 4;
_mapView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[self.view addSubview:_mapView];
_mapView.showsUserLocation = YES;
[_mapView setConstraintsSouthWest:[_mapView.tileSource latitudeLongitudeBoundingBox].southWest
northEast:[_mapView.tileSource latitudeLongitudeBoundingBox].northEast];
RMPointAnnotation *annotation = [[RMPointAnnotation alloc] initWithMapView:_mapView
coordinate:_mapView.centerCoordinate andTitle:#"Hello, world!"];
[_mapView addAnnotation:annotation];
}
and this is the part, where I try to call the LowContentMap viewController, from the ViewController - main ViewController:
- (void) prepareForSegue:(UIStoryboardSegue *) segue sender:(id) sender {
if ([segue.identifier isEqualToString:#"Hello, world!"]) {
//LowContentMap *lowContentMap = segue.destinationViewController;
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:[NSBundle mainBundle]];
LowContentMap *lowContentMap = [storyboard instantiateViewControllerWithIdentifier:#"lowContentMap"];
lowContentMap.lcm = _vc;
}}
This is the part of the code, that should be filled in:
- (void)mapView:(RMMapView *)mapView annotationView:(RMPointAnnotation *)annotation calloutAccessoryControlTapped:(UIControl *)control{
[self performSegueWithIdentifier:#"ShowSomeViewController" sender:annotation];
}
It would be really great, if somebody would try to resolve the problem.
I followed the discusion between Noa and Kronos at:
Setting up a detail view controller using a segue
but I still think, the part with the 'id' is something I am doing wrong. Thanks in advance.
1. I think your problem is that you don't know how to display another viewController
You should give the "View Controller Programming Guide" a good read, especially the part "Presenting View Controllers from Other View Controllers"
http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/Introduction/Introduction.html
I also recommend to check out some of the awesome WWDC videos that show how to use ViewControllers.
2. How to create and display a viewController
There are many ways to do it. E.g. using the storyboard to create and display the viewController, define a protocol in the child controller, override "performSegueWithIdentifier" to set the delegate and implement the protocol to dismiss the vc.
However, in your case, it seems to make sense to do it all programmatically. Thus, you need to:
a) find the right place to add your action
b) alloc and init your view controller:
MyController *myController = [[MyController alloc] init];
// setup as required, there should be at least a delegate (being able to dismiss the view)
myController.delegate = self;
If you have designed your viewController in a storyboard, you might want to use this alloc/init routine instead:
MyController *myController = [[UIStoryboard storyboardWithName:#"Main.storyboard" bundle:nil] instantiateViewControllerWithIdentifier:#"MyController"];
myController.delegate = self;
c) display your new view controller;
this depends on if you have a navigationController:
[self.navigationController pushViewController:myController animated:YES];
...or if you want to present it modally:
[self presentViewController:myController animated:YES completion:NULL];
d) dismiss when done;
when your other controller is done with whatever it does, it should inform its delegate (implement your own protocol!) that it's done and should be dismissed. The delegate is the original viewController that created (alloc'd/inited) the "myController":
// this method should be defined in a protocol and implemented in the vc that created (and owns) the child view controller
// typically, this is the parent view controller
- (void)done {
[self dismissViewControllerAnimated:YES completion:NULL];
}
if you used a navigationController it's not -dismissViewControllerAnimated:, but
[self.navigationController popViewControllerAnimated:YES];
hope this helps to clarify things
Is is possible to have a UIView preloaded so that it will load faster when the user taps on button to load it? Currently I've got a library of informaiton that I'm attempting to load when the user taps a button, and for now it seems to be "ok" , but it makes the navigation to the page choppy, because of all the information in the library it's loading.
Thanks in advance!
It should be possible to split the setup of a View Controller from code that displays the view after a button is pushed. This will eliminate the lag when the button but the task to setup the view controller still need to be done sometime during execution (You can for example put it in the ViewdidAppear method so it is executed while waiting for the button to be pushed.
Take this code for example:
-(IBAction) button_pushed {
/*setup */
NewVC *vc = [[NewVC alloc] init];
vc.var1 = var1;
vc.var2 = x;
[vc setup];
/*display */
[self.navigationController pushViewController:vc animated:NO];
return;
}
You can split the code that setup the view from the code that displays the view
into :
#synthesize vc;
…..
- (NewVC) setup {
//setup
NewVC *vc1 = [[NewVC alloc] init];
vc.var1 = var1;
vc.var2 = x;
[vc setup];
return(vc1);
}
-(void) ViewDidAppear {
if (setupready) {
vc = [self setup];}
return;
}
-(IBAction) button_pushed:(ID) sender {
//display
[self.navigationController pushViewController:vc animated:NO];
return;
}
I'm confused. I have a navigation controller with a BarItem which opens a first view. After some work is done, I want this view to disappear and I want a second view to open.
root view: navigation controller
first view: activity indicator, where some data is put together
second view: MFMailComposeViewController
In the root view, the BarItem runs these lines to open the first view:
IndicatorViewController *indicator = [[IndicatorViewController alloc] initWithNibName:#"IndicatorViewController" bundle:nil];
indicator.view.backgroundColor = [UIColor clearColor];
self.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentModalViewController:indicator animated:YES];
The first view (IndicatorViewController) does some work and finally runs
[self dismissModalViewControllerAnimated:YES];
This works fine. But - how do I open the second view?
I tried this:
I open the second view. After closing the second view, my first view pops up again (since it is still there) and get's dismissed at this point. This code is placed in the first view:
- (void) viewDidAppear:(BOOL)animated {
static BOOL firstTime = YES;
if (firstTime) {
//do stuff that takes some time (that's why I show the indicator)
MailViewController *controller = [[MailViewController alloc] init];
if (controller)
[self presentModalViewController:controller animated:YES];
firstTime = NO;
} else {
[self dismissModalViewControllerAnimated:YES];
}
}
Since the first view pops up again, the user can see the indicator one more time, after the second view is closed - and that is not what I want.
What am I missing here? What would be the better way to do this?
I would do something like this. Make a navigationController, and make the first view as the root controller. Then do something like this:
FirstView.m
- (void)viewDidLoad
{
[super viewDidLoad];
[self.navigationController setNavigationBarHidden:YES];
}
- (void) nextView { // however you get to your next view, button/action/etc.
UIViewController *screen = [self.storyboard instantiateViewControllerWithIdentifier:#"yourIdentifier"];
[self.navigationController pushViewController:screen animated:YES];
}
Then in the second view:
SecondView.m
- (void) nextView { // however you get to your next view, button/action/etc.
UIViewController *screen = [self.storyboard instantiateViewControllerWithIdentifier:#"yourIdentifier"];
[self.navigationController pushViewController:screen animated:YES];
}
And finally in the rootview:
RootView.m
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *navStack = [NSArray arrayWithObject:self];
self.navigationController.viewControllers = navStack;
[self.navigationController setNavigationBarHidden:NO];
}
This will make your RootView the new rootview of the NavigationController.
self.navigationController.viewControllers
is the array with all the ViewControllers that are on the navcontrollers stack. The first object is the rootcontroller. If we replace the whole array with our own array, it knows only one item. You CAN go back by dismissing if that's what you want though. This isn't the prettiest way of doing it, but it's not the worst either.