I have a segmented control which when clicked the user will be forced to enter a password.
After a successful check the modal screen should dismiss and in the controller with the segmented control a method is called and a segue should be performed to another controller.
The segue itself works but not after the login check. I think this is a problem with the "self"...
Code of delegate class:
#protocol LoginUserControllerDelegate
- (void)proceedAfterLogin:(BOOL)proceedToNextController;
#end
#interface LoginUserController : UIViewController {
IBOutlet UITextField *loginPWD;
id<LoginUserControllerDelegate> _delegate;
}
#property (nonatomic, retain) UITextField *loginPWD;
#property (nonatomic, assign) id<LoginUserControllerDelegate> delegate;
- (void)checkLogindata; // checks for correct password
#end
#implementation LoginUserController
#synthesize loginPWD;
#synthesize delegate = _delegate;
- (void)checkLogindata {
...
if ([tempDBPWD isEqualToString:tempLoginPWD]) {
if (_delegate != nil) {
[self dismissModalViewControllerAnimated:YES];
[_delegate proceedAfterLogin:YES];
}
}
...
}
#end
The segmented controller with the method:
#interface StartViewController : UIViewController <LoginUserControllerDelegate> {
UISegmentedControl *segmentedControl;
LoginUserController *_loginUserController;
}
#property (nonatomic,retain) IBOutlet UISegmentedControl *segmentedControl;
#property (nonatomic, retain) LoginUserController *loginUserController;
- (IBAction)segmentedControlIndexChanged:(id)sender;
#end
#implementation StartViewController
#synthesize segmentedControl;
#synthesize loginUserController = _loginUserController;
- (IBAction)segmentedControlIndexChanged:(id)sender
{
if (self.segmentedControl.selectedSegmentIndex == 0) {
// get delegate
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
UIStoryboard *storyboard = appDelegate.window.rootViewController.storyboard;
LoginUserController *loginUserControllerView = [storyboard instantiateViewControllerWithIdentifier:#"LoginUserViewID"];
loginUserControllerView.delegate = self;
// now show screen
[self presentModalViewController:loginUserControllerView animated:YES];
} else {
}
}
- (void)proceedAfterLogin:(BOOL)proceedToNextController
{
if (proceedToNextController) {
// yes, correct login now perform the segue to the controller
[[self segmentedControl] setSelectedSegmentIndex:UISegmentedControlNoSegment];
[self performSegueWithIdentifier:#"NextControllerSegueID" sender:self];
}
}
#end
I think the [self performSegueWithIdentifier:#"NextControllerSegueID" sender:self]; is the problem, because self is not correct. Is this where the error arises and how can I achieved my desired behaviour?
You're close, but you need to return to the delegate, and then call dismissModalViewControllerAnimated:YES. A modal controller can't dismiss itself, so you need to do your login, call back to the delegate, and have the delegate dismiss the modal controller.
Related
I'm trying to implement a delegate method for my button ... I think I did everything correctly but do not understand why I can not make it work ... My button does not respond to any commands looks dead ... ...
My button is located in the ViewController "B" and the function it has to perform is located in the ViewController "A"
This is my code
viewControllerB.h
#protocol UNI_TableLoginDelegate <NSObject>
-(void)showPassw;
#end
#interface viewControllerB : UITableViewController
#property (nonatomic, weak) id <UNI_TableLoginDelegate> delegate;
#end
viewControllerB.m (here I connected the action button via my storyboard)
#implementation viewControllerB
#synthesize delegate;
- (void)viewDidLoad {
[super viewDidLoad];
}
- (IBAction)showReset:(id)sender {
[delegate showPassw];
}
viewControllerA.m
#import "viewControllerB.h"
#interface viewControllerA () <UNI_TableLoginDelegate>
- (void)viewDidLoad {
[super viewDidLoad];
viewControllerB *tableLogin = [[viewControllerB alloc] init];
tableLogin.delegate = self;
}
//Delegate Method
-(void)showPassw {
if (containerTable.frame.origin.y == 56) {
NSLog(#"ssss");
}
else {
NSLog(#"hdhdh");
}
}
You need to set the delegate in your ViewController A.
Let's say you have this method that calls right before dismissing the ViewController A:
-(void)dismissThisController{
// you need to set the delegate value
[self.delegate yourDelegateMethod:withValueYouWantToSend];
[self dismissViewControllerAnimated:YES completion:^{
}];
}
and in your View Controller B, you have this delegate method:
#pragma mark ViewController A delegate
-(void)yourDelegateMethod:(someType)value{
//receive your delegate value here
}
My goal is to start a timer in the app delegate and use it to call methods in other view controllers. When these methods are called they will update the text of the UILabel. I'm performing the method on the main thread but I can't figure out why the UILabel is not being updated. I know the method in the view controller is being called but the UILabel doesn't get updated. I also verified the IBOutlet connection in Interface Builder. I am using storyboard to lay out my views and attach the view controllers to those views. What am I doing wrong?
In my AppDelegate.m:
#import "AppDelegate.h"
#import "GreyViewController.h"
#interface AppDelegate ()
#property (nonatomic) int counter;
#property (strong, nonatomic) GreyViewController *greyClass;
#end
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSTimer *timer;
timer = [NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:#selector(performOnMain)
userInfo:nil
repeats:YES];
return YES;
}
- (GreyViewController *)greyClass {
if (!_greyClass) {
_greyClass = [[GreyViewController alloc] init];
}
return _greyClass;
}
- (void)performOnMain {
[self performSelectorOnMainThread:#selector(updateLabel) withObject:nil waitUntilDone:YES];
}
- (void)updateLabel {
self.counter++;
NSLog(#"appdelegate counter %i", self.counter);
[self.greyClass updateGreyLabel:[NSString stringWithFormat:#"%i", self.counter]];
}
#end
The GreyViewController.h is:
#import <UIKit/UIKit.h>
#interface GreyViewController : UIViewController
#property (strong, nonatomic) NSString *greyString;
#property (weak, nonatomic) IBOutlet UILabel *greyLabel;
- (void)updateGreyLabel:(NSString *)string;
#end
The method in my GreyViewController.m:
- (void)updateGreyLabel:(NSString *)string {
self.greyLabel.text = string;
NSLog(#"greyviewcontroller string %#", string);
}
Every time you call:
GreyViewController *greyClass = [[GreyViewController alloc] init];
in your "updateLabel" method (i.e. every two seconds) you're instantiating a new GreyViewController. It's very likely you do not want to do that.
Instead, instantiate/create it once (or create it in your storyboard or XIB file) and the update the label which is connected to an outlet.
I've got a ViewController inside a navigation controller that needs to present a modal.
The ViewController has this as its header:
#interface ViewController : BaseViewController<AuthenticateDelegate>
and in the IBAction that presents the modal:
AuthenticationController *authVC = [self.storyboard instantiateViewControllerWithIdentifier:#"AuthControllerView"];
authVC.delegate = self;
[self presentModalViewController:authVC animated:YES];
The AuthenticationController has this in its .h file:
#interface AuthenticationController: BaseViewController<UITextFieldDelegate>
#property (nonatomic, assign) id <AuthenticateDelegate> delegate;
#end
As you can see, I have assigned "self" (the ViewController) as the delegate to the AuthenticationController, but for some reason, the delegate is in:
- (IBAction)SubmitAuthentication:(id)sender;
{
[self.delegate validateUser:lblUsername.text :lblPassword.text];
[self dismissModalViewControllerAnimated:YES];
}
Any help will be appreciated.
you must create delegate property as below.
#property (nonatomic, strong) id <AuthenticateDelegate> delegate;
I'm creating a 3 layer navigation popup controller and on the 3rd popup controller I have a delegate method to access dismissPopup method that is in the parent class. I can't seem to call it, my NSLog messages in the function in the parent class isn't even showing so I must be either using delegation wrong or I'm calling it incorrectly.
The 3 classes ParentViewController has a toolbar with a button that brings up the table view --> RegionViewController is the First table view controller with items --> ConusViewController is the 2nd table view controller that is pushed onto the navigation stack. I'm trying to call the method dismissPopover that is in the parent method with a delegation after the selection is clicked on so the whole popover goes away.
In the ConusViewController if the delegation had worked I would have seen "Method Accessed" from the function in the parent class. It doesn't show so I must be using delegation wrong.
Sorry for being so wordy on my post, I wanted to be complete on what I'm trying to do here. Thanks.
ParentViewController.h
#import <UIKit/UIKit.h>
#import "ConusViewController.h"
#interface EnscoWXViewController : UIViewController <ConusViewControllerDelegate> {
UIPopoverController *popoverController;
IBOutlet UIWebView *webImageDisplay;
ConusViewController *cViewController;
}
#property (nonatomic, retain) UIPopoverController *popoverController;
#property (nonatomic, retain) UIWebView *webImageDisplay;
#property (nonatomic, retain) ConusViewController *cViewController;
-(IBAction) buttonShowRegion:(id) sender;
#end
ParentViewController.m
#import "ParentViewController.h"
#import "RegionViewController.h"
#implementation ParentViewController
#synthesize cViewController;
-(IBAction) buttonShowRegion:(id) sender {
...
}
-(void)dismissPopover {
[popoverController dismissPopoverAnimated:YES];
printf("Method Accessed\n");
}
- (void)viewDidLoad {
cViewController = [[ConusViewController alloc] init];
cViewController.delegate = self;
[super viewDidLoad];
}
RegionViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
switch (indexPath.row) {
case 0: {
ConusViewController *conusViewController = [[ConusViewController alloc] initWithNibName:#"ConusViewController" bundle:nil];
conusViewController.contentSizeForViewInPopover = CGSizeMake(320, 350);
[self.navigationController pushViewController:conusViewController animated:YES];
[conusViewController release];
break;
}
case 1: {
break;
}
}
}
ConusViewController.h
#import <UIKit/UIKit.h>
#protocol ConusViewControllerDelegate <NSObject>
#required
- (void)dismissPopover;
#end
#interface ConusViewController : UITableViewController {
NSMutableArray *conusItems;
id delegate;
}
#property (nonatomic, assign) id <ConusViewControllerDelegate> delegate ;
#end
ConusViewController.m
#import "ConusViewController.h"
#import "ParentWXViewController.h"
#implementation ConusViewController
#synthesize delegate;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *itemRequested = [conusItems objectAtIndex:indexPath.row];
NSLog(#"logging: %#", itemRequested);
[delegate dismissPopover];
[itemRequested release];
}
Just before calling [delegate dismissPopover], check if delegate is actually set. It probably isn't.
I see in ParentViewController.m you create an instance of ConusViewController and set its delegate, but never display it. In RegionViewController.m you create another instance of ConusViewController without setting its delegate and that is the one that seems to be being displayed.
Not sure if I missed it, but I never see you set the delegate property in ConusViewController. That needs to be set to an instance of the object that is to be delegated to (the object that has dismissPopover implemented in it).
According to the View Controller Programming Guide, delegation is the preferred method to dismiss a modal view.
Following Apple's own Recipe example, i have implemented the following, but keep getting warnings that the addNameController:didAddName method is not found...
NameDelegate.h
#protocol NameDelegate
- (void)addNameController:(AddName *)addNameController didAddName:(NSString *)name;
#end
AddName.h
#interface AddName : UIViewController {
UITextField *nameField;
id delegate;
}
- (IBAction)doneAction;
- (id)delegate;
- (void)setDelegate:(id)newDelegate;
#property (nonatomic, retain) IBOutlet UITextField *nameField;
#end
AddName.m
- (IBAction)doneAction {
[delegate addNameController:self didAddName:[nameField text]];
}
- (id)delegate {
return delegate;
}
- (void)setDelegate:(id)newDelegate {
delegate = newDelegate;
}
ItemViewController.h
#import "NameDelegate.h"
#interface ItemViewController : UITableViewController <NameDelegate>{
}
#end
ItemViewController.m
- (void)addItem:(id)sender {
AddName *addName = [[AddName alloc] init];
addName.delegate = self;
[self presentModalViewController:addName animated:YES];
}
- (void)addNameController:(AddName *)addNameController didAddName:(NSString *)name {
//Do other checks before dismiss...
[self dismissModalViewControllerAnimated:YES];
}
I think all the required elements are there and in the right place?
Thanks
You haven't specified that the delegate property of AddName has to conform to the NameDelegate protocol.
Use this code in AddName.h:
#import "NameDelegate.h"
#interface AddName : UIViewController {
UITextField *nameField;
id <NameDelegate> delegate;
}
#property(nonatomic, retain) IBOutlet UITextField *nameField;
#property(nonatomic, assign) id <NameDelegate> delegate;
- (IBAction)doneAction;
#end