Open viewController file from every Viewcontroller - objective-c

I am developing e-commerce application very similar like Flipkart.
Now I can visit my application without login. I mean initially I can skip login. But when I am going to purchase any item user should be be prompted to login.
Now client's requirement is there should be login button at every page of the application so, user should be navigated to login page from every page and after successfully login he should return to perticular page from when he/she went to login page.
Any idea how can I achieve this kind of functionality?

Step 1 : Create Base class
BaseViewController.h
#import <UIKit/UIKit.h>
#interface BaseViewController : UIViewController
-(void)takeMeToLogin;
#end
BaseViewController.m
#import "BaseViewController.h"
#interface BaseViewController () {
UIView *myTabBar;
UIButton *loginButton;
}
#end
#implementation BaseViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
loginButton = [UIButton buttonWithType:UIButtonTypeCustom];
loginButton.tag = 5566778897;
[loginButton addTarget:self action:#selector(takeMeToLogin) forControlEvents:UIControlEventTouchUpInside];
[loginButton setBackgroundImage:[UIImage imageNamed:#"login.png"] forState:UIControlStateNormal];
loginButton.frame = CGRectMake(x,y, width, height);
[self.view addSubview:backButton];
}
-(void) takeMeToLogin {
// code here to go to Login screen
}
Step 2: Use BaseViewController as your base class.
Now whenever you create any class, you will have as below.
#interface YourViewController : BaseViewController
By default you will have #interface YourViewController : UIViewController
Let me know if you need anything else
Edit 1
Regarding your comment, Fahim's solution is also working but it has one limitation that I have to create login button on navigation bar. I can't put login button anywhere in the screen., I will say, you can add it anywhere you want. Below is how.
In YourViewController.m have below.
UIButton *buttonThatYouWantToMove = (UIButton *)[self.view viewWithTag:5566778897];
[self.view addSubview:buttonThatYouWantToMove]; // if this don't work use insertSubview:aboveSubview:
buttonThatYouWantToMove.frame = CGRectMake(x,y,width,height); // this is very important
Done!!!
Let me know if you need further explanation.

I'd create MYBaseViewController and inherit from it in all other controller. I'd create a function which adds login button to navbar right item and a function which handles the login. This way, you'll keep everything in one place.
You can do the same in UIViewController category and call the methods in proper controllers, but personally I think that if that's solution for every single UIViewController it's less pretty.
If someone has better idea, I'd gladly hear about it.

Fahim's solution is also working but it has one limitation that I have to create login button on navigation bar. I can't put login button anywhere in the screen.
I approached differently.
I have created loginViewController.
Create protocol in loginViewController file.
Put button in every viewcontroller to open loginviewcontroller file
Modally open loginview controller
Most important thing is in my Stroryboard file I took loginviewcontroller file embedded in NavigationController and my NavigationController is modally attached with every ViewController.
In LoginViewController.h
#class LoginViewController;
#protocol LoginViewControllerDelegate <NSObject>
- (void)LoginViewControllerViewDidCancel:(LoginViewController *)controller;
- (void)LoginViewControllerViewDidDone:(LoginViewController *)controller;
#end
#interface LoginViewController : UIViewController
#property (nonatomic, weak)id <LoginViewControllerDelegate> delegate;
#end
In LoginViewController.m
- (IBAction)didCancel:(UIBarButtonItem *)sender {
[self.delegate LoginViewControllerViewDidCancel:self];
}
- (IBAction)didDone:(id)sender {
[self.delegate LoginViewControllerViewDidDone:self];
}
Now same code for FirstViewController, SecondViewController etc.
FirstViewController.m
#import "LoginViewController.h"
#interface FirstViewController ()<LoginViewControllerDelegate>
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"LoginView"]) {
UINavigationController *navigationController = segue.destinationViewController;
LoginViewController *loginViewController = [navigationController viewControllers][0];
loginViewController.delegate = self;
}
if ([segue.identifier isEqualToString:#"Thirdpage"]) {
}
}
#pragma loginViewController delegate
-(void) LoginViewControllerViewDidCancel:(LoginViewController *)controller{
//Your Logic
[self dismissViewControllerAnimated:YES completion:nil];
}
-(void) LoginViewControllerViewDidDone:(LoginViewController *)controller{
//Your Logic
[self dismissViewControllerAnimated:YES completion:nil];
}
It works for me like a charm..

Related

How to make dissappear the text in the textfield of 1st view controller when clicked on Logout button in 2nd view controller?

- (IBAction)loginButtonAction:(id)sender
{
[self.navigationController popToViewController:
[self.navigationController.viewControllers
objectAtIndex:self.navigationController.viewControllers.count -2]
animated:YES];
}
This is my logout code in 2nd view controller, i want to remove text
in login screen of user name and password when clicked on Logout
button.. Please can some one help me?
You can use delegate or NSNotification for this.
Delegate.
Lets you have two View Controller.. One is ViewController and other NextViewController and You want to logout from NextViewController and clear the text in ViewController.
Steps: In NextViewController.h
#import <UIKit/UIKit.h>
#protocol clearTextField <NSObject>
-(void)clearTextFieldInPreviousController: (NSString *)string;
#end
#interface NextViewController : UIViewController
#property (assign,nonatomic) id delegate;
#end
In nextViewController.m
- (IBAction)loginButtonAction:(id)sender
{
[_delegate clearTextFieldInPreviousController:#""];
[self.navigationController popToViewController:
[self.navigationController.viewControllers
objectAtIndex:self.navigationController.viewControllers.count -2]
animated:YES];
}
And In Your ViewController.m
-(void)clearTextFieldInPreviousController: (NSString *)string{
NSLog(#"Fired");
self.label.text =#"";
}
// Note before going to next controller. You will have to set the delegate.
– (IBAction)goNextButtonAction:(id)sender {
NextViewController *acontollerobject=[self.storyboard instantiateViewControllerWithIdentifier:#"NVCSID"];
acontollerobject.delegate=self; // protocol listener
[self.navigationController pushViewController:acontollerobject animated:YES];
}
you can visit this link for Demo Example
There are a number of ways to achieve this.
Use delegation to pass message to 1st viewcontroller about the logout event from 2nd view controller and reset views in the passed message implementation.
I will suggest you to make 2nd view controller as rootViewController and not to keep the login view as part of navigation stack. You can show the login controller as a modal viewController over the 2nd View controller.

Multiple webviews in one UIViewController

Lets say I have a UIViewController with two buttons, both going (push) to another UIViewController that has two UIWebViews (showing two different PDF files), how can I make sure that only the one I choose via the button is showed?
You need to pass some information to the UIViewController which has the UIWebViews, saying which button was pressed. Then, based on that information, decide which of the UIWebViews to display.
As you are using storyboards, I suggest you look into prepareForSegue. It will allow you to set a property on the destination view controller with something like the following. You should add this to the UIViewController which contains the buttons.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"buttonOne"]) {
ExampleViewController *destViewController = segue.destinationViewController;
destViewController.buttonClicked = #"One";
} else if ([segue.identifier isEqualToString:#"buttonTwo"]) {
ExampleViewController *destViewController = segue.destinationViewController;
destViewController.buttonClicked = #"Two";
}
}
You can then use the buttonClicked property in the destination view controller to decide which you should display. If you have two separate UIWebViews, you could choose to hide one using webViewOne.hidden = YES; and show the other using webViewTwo.hidden = NO;.
However, it would probably be neater to only have a single UIWebView. You could then use prepareForSeque to pass in the URL of the PDF you would like it to display, rather than just sending the name of the button clicked.
Assuming you webView is in a view controller called SecondViewController and your buttons are in the view controller called FirstViewController
1) Create an object in your SecondViewController.h
#interface SecondViewController : UIViewController
#property (nonatomic, strong) NSString *whichButtonClicked;
#end
2) Import SecondViewController in your FirstViewController
#import "SecondViewController.h"
3) In you button IBAction method in FirstViewController.m . use this code
- (IBAction) firstButtonClicked
{
SecondViewController *secondViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"secondView"];
secondViewController. whichButtonClicked = #"first"
[self.navigationController pushViewController:secondViewController animated:YES];
}
- (IBAction) secondButtonClicked
{
SecondViewController *secondViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"secondView"];
secondViewController. whichButtonClicked = #"second"
[self.navigationController pushViewController:secondViewController animated:YES];
}
PS Don't forget. In you Storyboard. Set Storyboard ID for SecondViewController as secondView
4) In your SecondViewController.m use this code to check which button
if ([self.whichButtonClicked isEqualToString:#"first"])
{
///display first web view here
}
else
{
//display second web view here
}
Hope this helps

How to modify the sender ViewController from the called ViewController?

I have a login view controller called from a Storyboard segue. When the user logs in correctly, I need to close the current ViewController, return to the caller ViewController and hide the login button.
How can I refer to the sender ViewController, to hide the button? Do I have to pass an instance of the root ViewController to the login or is there another way?
Use delegation.
For your DetaliViewControler create a protocol, like
#protocol DetailViewControllerDelegate <NSObject>
-(void)successFullyLoggedInOnController:(DetailViewController *) controller;
#end
add a delegate declaration to DetailViewController's interface like
#property (weak) id<DetailViewControllerDelegate> delegate;
Make the MasterViewController conform to the protocol.
-(void)successFullyLoggedInOnController:(DetailViewController *) controller
{
[self.loginButton setHidden:YES];
}
Now just before the MasterViewController displays the DetailViewController, doe something like
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"DetailViewSegue"]) {
DetailViewController *vc = segue.destinationViewController;
vc.delegate = self;
}
}
In the DetailViewController once the credential where entered and verified call
[self.delegate successFullyLoggedInOnController:self];
and dismiss the DetailViewController
You should use delegation. Make the VC with the button the other one's delegate. When log in is successful, you dismiss your VC and call the delegate method to hide the button.

How to go back two viewControllers before, from ABPeoplepicker delegate method

I'm developing an app which uses ABPeopleViewController, and i want to when the user finalized choosing a contact, go backward two viewcontroller before.
Here's how i am arriving to ABPeoplePickerNavigationController:
Tap in a button of a main view controller --> load modal (dialog) view controller --> tap in a button of the modal view controller --> load ABContacts.
I'm implementing the delegate of ABContacts in the modal view, which in turn has a delegate in the main view controller.
I want to go back from ABPeoplePicker delegate method to the main view controller.
Hope this understands and someone can help me, i didn't find anything like this.
My MainViewController.h:
#protocol ModalViewDialogDelegate
- (void)didReceiveMail:(NSString *)mail;
#end
#interface SetUpViewController : UIViewController<UITextFieldDelegate, ModalViewDialogDelegate>{
}
//...
My MainViewController.m:
//...
- (void)didReceiveMail:(NSString *)mail{
[self.presentedViewController dismissViewControllerAnimated:YES completion:nil];
//...
My ModalView.h:
#import <AddressBook/AddressBook.h>
#import <AddressBookUI/AddressBookUI.h>
#protocol ModalViewDialogDelegate;
#interface DialogViewController : UIViewController<ABNewPersonViewControllerDelegate, ABPeoplePickerNavigationControllerDelegate>{
id<ModalViewDialogDelegate> delegate;
}
#property (nonatomic, assign) id<ModalViewDialogDelegate> delegate;
#property (nonatomic, retain) NSString * mailSelected;
//...
My modalView.m:
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier{
//...here i get the email person property and then i want to go backwards to the main view controller, not the modal.
[self dismissViewControllerAnimated:YES completion:nil];
//don't know if it's ok like this, because in the implementation also dismiss presented viewcontroller.
[_delegate didReceiveMail:self.mailSelected];
return NO;
}
return YES;
}
Try putting this
[_delegate didReceiveMail:self.mailSelected];
inside the completion block of the
[self dismissViewControllerAnimated:YES completion:nil];
that precedes it.
(If that doesnt work you can simply call the dissmiss twice on your maincontroller delegate method, each dismiss will remove one from the stack)
[[[self presentingViewController] presentingViewController] dismissViewControllerAnimated:NO completion:nil];

Understanding custom Delegate

So I have an app, and in the app there is a tableView, I have a uinavigationbarbutton that presents a modal viewController. When the user hits a go button in the modal interface, I want it dismiss the modal view and get some of the information in the modal view. I will than put that info in the tableView. To do this, I wrote a custom delegate, but it doesn’t work. I included my code below. Thanks for any help.
TrackerMainViewController.h //the tableView
#import "NewItemViewController.h"
#interface TrackerMainViewController : UITableViewController <UITableViewDelegate, DetailDelegate>
TrackerMainViewController.m
-(void)finishedAddingFoodItemFromDetail:(NSDate *)date whatWasEaten:(NSString *)whatFood whichMeal:(NSString *)meal {
NSLog(#"in delegate method here");
[self.tableView reloadData];
[self dismissModalViewControllerAnimated:YES];
}
NewItemViewController.h // the modal view
#protocol DetailDelegate <NSObject>
-(void)finishedAddingFoodItemFromDetail:(NSDate *)date whatWasEaten:(NSString *)whatFood whichMeal:(NSString *)meal;
#end
#interface NewItemViewController : UIViewController {
id <DetailDelegate> _delegate;
}
#property (nonatomic, retain) id <DetailDelegate> delegate;
#end
NewItemViewController.h
#implementation NewItemViewController
#synthesize delegate = _delegate;
//the go button in the modal view
- (IBAction)Go:(id)sender {
[self.delegate finishedAddingFoodItemFromDetail:[NSDate date] whatWasEaten:#"chicken" whichMeal:#"breakfast"];
}
I put a log in both the go button and in the implementation of the delegate in the tableview, but only the go log is being called.
Thanks
In the code you posted, you dont set the delegate. You need to set it similar to this detailView.delegate = self, otherwise it is nil. You can send messages to a nil-object without any warning and error, nothing will happen.