i'm trying to build a quiz that sets the value of a UILabel dynamically through code.
i've done this successfully before, but for some reason it's not working this time. i suspect it's because the structure of this app is different. i've tried different fixes but haven't been able to get it to work.
the way my app is set up, i have a view controller with a view that has a segmented control. when you press one of the switches on the segmented control, it inserts a subview like this:
menuTable.hidden = YES;
additionPracticeController *additionPractice = [[additionPracticeController alloc]
initWithNibName:#"additionPractice"
bundle:nil];
self.addPracticeController = additionPractice;
[self.view insertSubview:additionPractice.view atIndex:0];
[additionPractice release];
the view controller for that subview displays its view like this:
- (void)viewWillAppear:(BOOL)animated{
firstNumberString = [NSString stringWithFormat:#"%d",arc4random() % 10];
firstNumberLabel.text = firstNumberString;
secondNumberLabel.text = secondNumberString;
[super viewWillAppear:animated]}
my outlets are connected and i can get the values to appear by setting them statically from the nib (even though that's not what i want). i've tried to set firstNumberString equal to all sorts of values, but nothing shows up when i set the values through code.
i'd really appreciate it if someone could help me solve this problem.
It sounds like you have the label connected in Interface Builder. I would need to see more code to know exactly what you are doing wrong. Make sure you are using a property for your label. The below code is a simple example of how this works.
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
{
IBOutlet UILabel *_displayMessage;
}
#property (nonatomic, retain) UILabel *displayMessage;
#end
ViewController.m
#import "ViewController.h"
#implementation ViewController
#synthesize displayMessage = _displayMessage;
- (void)viewDidLoad
{
[super viewDidLoad];
self.displayMessage.text = #"Text Changed!";
}
- (void)viewDidUnload
{
self.displayMessage = nil;
[super viewDidUnload];
}
- (void)dealloc
{
[_displayMessage release];
[super dealloc];
}
#end
Instead of making your class a subclass of UIControl just implement this method below. When the user hits done or return the keypad will resign
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
To make the text field dismiss when the user taps outside of the text field.
Place this in ViewDidLoad:
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];
Place this method within the class:
-(void)dismissKeyboard
{
[aTextField resignFirstResponder];
}
Also if you want to dismiss the text field from another button spefically and not just a screen tap. Then just call this from within the button.
[your_textfield_name resignFirstResponder];
Related
I have a simple question, how to connect a textfield to another Control view, if I click on the textfield, instead of show the keyboard it jump to another view
Thanks for answers
In the delegate method of the TextField, wich is textFieldShouldBeginEditing, add code that go from current View to another View.
Or you can use tap gasture recognizer on TextField to get the touch.
Here is the code:
create a TextFied in your IB and connect it to .h file
#interface ViewController : UIViewController<UITextFieldDelegate>
#property (strong, nonatomic) IBOutlet UITextField *firstTF;
And in .m file add this
#synthesize firstTF;
- (void)viewDidLoad
{
[super viewDidLoad];
firstTF.delegate= self;
}
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
secondViewController *ainfoController = [[secondViewController alloc] initWithNibName:#"secondViewController" bundle:nil];
[self presentModalViewController:ainfoController animated:YES];
return YES;
}
If you are adding the Textfield by code then,
UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(x, y, width, height)];
textField.delegate = self;
[self.view addSubview:textField];
and add this method
- (BOOL) textFieldShouldBeginEditing:(UITextField *)textField{
// you can add the code for present a new viewController here
return NO;
}
make sure you have added UITextFieldDelegate in your .h file
I really don't get in why you need this but as a developer we do firmly believe to implement all scenarios, so in your case, you can achieve the same by following the any one beneath mentioned tacts:
1) In this approach, you need to override the textfieldshouldbegin delegate and use the navigate code for moving from one screen to another and don't forget to call resignFirstResponder here.
2) While in this second approach what you can do, just overlap a custom button(with neither image nor any text) and just on his click event method write your navigation code to move another screen.
Do that stuff, you'll get what you want and in case still you find any difficulty just shout over me.
i have a view which contains some text fields and picker views and one button,when clicked on the button all these textfields and picker view should appear again in the same view.Now how should i take the initial view and how to load the same view with the previous view when clicked on the button.
Thanks in advance..
Setting the Frames an Adding subview (text fields and picker views) on the button click , you can appear those subviews to the main view.
Or else you can initially put them all in the main view and initially hide them. And on the button click set them Hidden : NO.
Here is the approach:
On your View controller : Add a button and a UIScrollView.
Create an independent view say MyView containing all your TextFields and pickers. (you can create this via xib or via code)
In ViewDidLoad method of your controller add this MyView on UIScrollView.
On onButtonPressed similarly add MyView on UIScrollView.
If I got your problem then this code might help you. I am adding only text field on button click event. So I think it might give you idea for another views and you can do the same with another views. I am giving you .m file, hope you can write .h file. Here is my .m file looks like -
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize btn = _btn; // IBOutlet of UIButton
#synthesize txtFieldOne = _txtFieldOne; // IBOutlet of UITextField
#synthesize txtFieldTwo = _txtFieldTwo; // IBOutlet of UITextField
- (void)viewDidLoad
{
newYCoordinateForNewTxtFld = 40.0; // newYCoordinateForNewTxtFld is of type CGFloat
frame = self.txtFieldTwo.frame; // frame is of type CGRect
[super viewDidLoad];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return true;
}
// TextField Delegate Method you might required in your project
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
- (IBAction)btnClicked:(id)sender
{
// I am giving u a simple idea, so written simple code. You can make code more usable with ur view by adding various functions, loops, etc ,etc.
int tagValue = 0;
UITextField *newTextField = [[UITextField alloc]initWithFrame:CGRectMake(frame.origin.x, frame.origin.y+newYCoordinateForNewTxtFld, frame.size.width, frame.size.height)];
newTextField.delegate = self;
newTextField.tag = tagValue++;
frame = newTextField.frame;
newTextField.backgroundColor = [UIColor whiteColor];
[newTextField setBorderStyle:UITextBorderStyleRoundedRect];
[self.view addSubview:newTextField];
newTextField = nil;
newTextField = [[UITextField alloc]initWithFrame:CGRectMake(frame.origin.x, frame.origin.y+newYCoordinateForNewTxtFld, frame.size.width, frame.size.height)];
newTextField.tag = tagValue++;
newTextField.delegate = self;
frame = newTextField.frame;
newTextField.backgroundColor = [UIColor whiteColor];
[newTextField setBorderStyle:UITextBorderStyleRoundedRect];
[self.view addSubview:newTextField];
}
#end
I'm looking to create a sizeable subview that's draggable like this:
If there is an IBAction that takes you to the next View (SecondViewController) and when it does, there's another IBAction there and when you click on that one, it creates a SubView that's about half of the size of the current screen you're in (SecondViewController) that shows the third view controller that would be created? Also, how would you make that subView draggable? Thank you for helping.
Sorry, just to be clear, you want your second view controller to have a button that when tapped, adds your third view controller taking up half the screen at the bottom?
If this is the case then you can do this with the new view controller containers in iOS5.
Ok, so you have three view controllers. For the sake of this lets say your class are called FirstViewController, SecondViewController and ThirdViewController.
I assume from what you say that you already have you instance of FirstViewController with a button, that moves you on to an instance of SecondViewController, and that the issue is then getting SecondViewController to add an instance of ThirdViewController to the bottom half of the screen when a button is pressed.
The .m file for SecondViewController will need to do something like this:
#import "ThirdViewController.h"
#interface SecondViewController ()
#property (retain) ThirdViewController *thirdViewConroller;
- (void)buttonTap;
#end
#implementation SecondViewController
#synthesize thirdViewConroller = _thirdViewConroller;
- (void)dealloc {
self.thirdViewConroller = nil;
[super dealloc];
}
- (void)loadView {
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.titleLabel.text = #"Show third controller";
[button addTarget:self action:#selector(buttonTap) forControlEvents:UIControlEventTouchUpInside];
button.frame = // Some CGRect of where you want the button to be
[self.view addSubview:button];
}
- (void)buttonTap {
// When the button is tapped, create an instance of your ThirdViewController and add it
self.thirdViewConroller = [[ThirdViewController alloc] initWithFrame:/* Some CGRect where you want the controller to be */ ];
[self.thirdViewConroller willMoveToParentViewController:self];
[self addChildViewController:self.thirdViewConroller];
[self.thirdViewConroller didMoveToParentViewController:self];
}
#end
This should give you a button on your second controller, that will create and add you third controller. Make sure yo us till have all the standard methods that you had before, this should be in addition to what you have.
In your interface for ThirdViewController:
#interface ThirdViewController : UIViewController <NSObject>
- (id)initWithFrame:(CGRect)frame;
#end
Then in the implementation of your ThirdViewController:
- (id)initWithFrame:(CGRect)frame {
self = [super initWithNibName:nil bundle:nil];
if (self) {
self.view.frame = frame;
// Do your init stuff here
}
return self;
}
It should then handle adding the views and such forth.
Make sure your thirdViewController class has a valid initWithFrame: initialiser method.
This should do the trick, if you need any further help let me know :)
I'm trying to work out the "best" way to use a UISegmentedControl for an iPhone application. I've read a few posts here on stackoverflow and seen a few people's ideas, but I can't quite sort out the best way to do this. The posts I'm referring to are:
Changing Views from UISegmentedControl
and
How do I use a UISegmentedControl to switch views?
It would seem that the options are:
Add each of the views in IB and lay them out on top of each other then show/hide them
Create each of the subviews separately in IB, then create a container in the main view to populate with the subview that you need
Set up one really tall or really wide UIView and animate it left/right or up/down depending on the selected segment
Use a UITabBarController to swap out the subviews - seems silly
For tables, reload the table and in cellForRowAtIndex and populate the table from different data sources or sections based on the segment option selected (not the case for my app)
So which approach is best for subview/non-table approaches? Which is the easiest to implement? Could you share some sample code to the approach?
Thanks!
I've come across this requirement as well in an iPad application.
The solution I came to was to create specialized view controllers for
each style of view to handle business logic relating to those views
(ie. relating to each segment), and programatically add/remove them as
subviews to a 'managing' controller in response to selected segment
index changes.
To do this, one has to create an additional UIViewController subclass that manages
UISegmentedControl changes, and adds/removes the subviews.
The code below does all this, also taking care of a few caveats/extras:
viewWillAppear/viewWillDisappear/etc, aren't called on the subviews
automatically, and need to be told via the 'managing' controller
viewWillAppear/viewWillDisappear/etc, aren't called on 'managing'
controller when it's within a navigation controller, hence the
navigation controller delegate
If you'd like to push onto a navigation stack from within a
segment's subview, you need to call back on to the 'managing' view
to do it, since the subview has been created outside of the
navigation hierarchy, and won't have a reference to the navigation
controller.
If used within a navigation controller scenario, the back button is
automatically set to the name of the segment.
Interface:
#interface SegmentManagingViewController : UIViewController <UINavigationControllerDelegate> {
UISegmentedControl * segmentedControl;
UIViewController * activeViewController;
NSArray * segmentedViewControllers;
}
#property (nonatomic, retain) IBOutlet UISegmentedControl * segmentedControl;
#property (nonatomic, retain) UIViewController * activeViewController;
#property (nonatomic, retain) NSArray * segmentedViewControllers;
#end
Implementation:
#interface SegmentManagingViewController ()
- (void)didChangeSegmentControl:(UISegmentedControl *)control;
#end
#implementation SegmentManagingViewController
#synthesize segmentedControl, activeViewController, segmentedViewControllers;
- (void)viewDidLoad {
[super viewDidLoad];
UIViewController * controller1 = [[MyViewController1 alloc] initWithParentViewController:self];
UIViewController * controller2 = [[MyViewController2 alloc] initWithParentViewController:self];
UIViewController * controller3 = [[MyViewController3 alloc] initWithParentViewController:self];
self.segmentedViewControllers = [NSArray arrayWithObjects:controller1, controller2, controller3, nil];
[controller1 release];
[controller2 release];
[controller3 release];
self.navigationItem.titleView = self.segmentedControl =
[[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:#"Seg 1", #"Seg 2", #"Seg 3", nil]];
self.segmentedControl.selectedSegmentIndex = 0;
self.segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;
[self.segmentedControl addTarget:self action:#selector(didChangeSegmentControl:) forControlEvents:UIControlEventValueChanged];
[self didChangeSegmentControl:self.segmentedControl]; // kick everything off
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.activeViewController viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self.activeViewController viewDidAppear:animated];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.activeViewController viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
[self.activeViewController viewDidDisappear:animated];
}
#pragma mark -
#pragma mark UINavigationControllerDelegate control
// Required to ensure we call viewDidAppear/viewWillAppear on ourselves (and the active view controller)
// inside of a navigation stack, since viewDidAppear/willAppear insn't invoked automatically. Without this
// selected table views don't know when to de-highlight the selected row.
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
[viewController viewDidAppear:animated];
}
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
[viewController viewWillAppear:animated];
}
#pragma mark -
#pragma mark Segment control
- (void)didChangeSegmentControl:(UISegmentedControl *)control {
if (self.activeViewController) {
[self.activeViewController viewWillDisappear:NO];
[self.activeViewController.view removeFromSuperview];
[self.activeViewController viewDidDisappear:NO];
}
self.activeViewController = [self.segmentedViewControllers objectAtIndex:control.selectedSegmentIndex];
[self.activeViewController viewWillAppear:NO];
[self.view addSubview:self.activeViewController.view];
[self.activeViewController viewDidAppear:NO];
NSString * segmentTitle = [control titleForSegmentAtIndex:control.selectedSegmentIndex];
self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:segmentTitle style:UIBarButtonItemStylePlain target:nil action:nil];
}
#pragma mark -
#pragma mark Memory management
- (void)dealloc {
self.segmentedControl = nil;
self.segmentedViewControllers = nil;
self.activeViewController = nil;
[super dealloc];
}
#end
Hope this helps.
I'd go with the second option you mention, creating the subviews in IB and swapping them in and out of a main view. This would be a good opportunity to use UIViewController, unsubclassed: in your initial setup, create a controller using -initWithNibName:bundle: (where the first parameter is the name of the NIB containing the individual subview, and the second parameter is nil) and add its view as a subview of your main view as necessary. This will help keep your memory footprint low: the default behavior of a UIViewController when receiving a memory warning is to release its view if it has no superview. As long as you remove hidden views from the view hierarchy, you can keep the controllers in memory and not worry about releasing anything.
(edited in response to comment:)
You don't need to subclass UIViewController, but you do need separate XIBs for each view. You also don't need to add anything to the containing view in IB.
Instance variables, in the interface of whatever class is handling all this:
UIViewController *controllerOne;
UIViewController *controllerTwo;
UIViewController *currentController;
IBOutlet UIView *theContainerView;
In your setup (-applicationDidFinishLaunching: or whatever)
controllerOne = [[UIViewController alloc] initWithNibName:#"MyFirstView" bundle:nil];
controllerTwo = [[UIViewController alloc] initWithNibName:#"MySecondView" bundle:nil];
To switch to a controller:
- (void)switchToController:(UIViewController *)newCtl
{
if(newCtl == currentController)
return;
if([currentController isViewLoaded])
[currentController.view removeFromSuperview];
if(newCtl != nil)
[theContainerView addSubview:newCtl.view];
currentController = newCtl;
}
Then just call that with, e.g.,
[self switchToController:controllerOne];
Here's a great tutorial that explains this concept further: http://redartisan.com/2010/5/26/uisegmented-control-view-switching
and the github location to it: https://github.com/crafterm/SegmentedControlExample.git
The issue that I'm having is that I have My start page, then the user can select a button from there to open a settings page (Modal View). From the settings page the user selects the switch to turn on the PIN code page (another Modal View). I have been killing myself trying to implement this simple process. The app has a Nav&Tab Bar framework. I seem to can not get this right. The code Im using is as follows:
#import "SwitchResponderViewController.h"
#implementation SwitchResponderViewController
- (void)viewDidLoad {
[super viewDidLoad];
[sw addTarget:self action:#selector(switched) forControlEvents:UIControlEventValueChanged];
}
- (void)dealloc {
[secondController release], secondController = nil;
[super dealloc];
}
- (void)switched;
{
if ([sw isOn])
{
NSLog(#"On");
if (!secondController)
secondController = [[SecondViewController alloc] init];
[self presentModalViewController:secondController animated:YES];
}
else
{
NSLog(#"Off");
}
}
#end
I then create an IBOutlet UISwitch called sw in my view controller and hook it up in IB. However I cant get it to compile and work. Any ideas?
Let me get this straight. You're using a UISwitch to go to a new view when it's toggled? Maybe that's not what's going on, but it looks like it to me, and that's a bad way to do things.
Also, you've got an extra semicolon after -(void)switched