i've got this method in my dashBoardViewController.m
- (void)demoSetup
{
self.tabBar.tintColor = [UIColor colorWithRed:(160/255.0) green:(97/255.0) blue:(5/255.0) alpha:1]; // set the tab bar tint color to something cool.
self.delegate = self; // Just to demo that delegate methods are being called.
}
#pragma UITabBarController Delegate
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
{
NSLog(#"UITabBarDelegate: shouldSelectViewController...");
return YES;
}
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController
{
NSLog(#"UITabBarDelegate: didSelectViewController...");
}
- (void)tabBarController:(UITabBarController *)tabBarController willBeginCustomizingViewControllers:(NSArray *)viewControllers
{
NSLog(#"UITabBarDelegate: willBeginCustomizingViewControllers...");
}
- (void)tabBarController:(UITabBarController *)tabBarController willEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed
{
NSLog(#"UITabBarDelegate: willEndCustomizingViewControllers...");
}
- (void)tabBarController:(UITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed
{
NSLog(#"UITabBarDelegate: didEndCustomizingViewControllers...");
}
i've got 4 linked on it, and a view with Facebook login
i need to pass from the view that contains Facebook login 2 datas (FBID, FBUSER) to my dashBoardViewController and from it pass the same data to all of my tabs, is it possible?
this is the dashBoardViewController.h
#import <UIKit/UIKit.h>
#import <FacebookSDK/FacebookSDK.h>
#import "BFPaperTabBarController.h"
#interface dashBoardViewController : BFPaperTabBarController <UITabBarControllerDelegate,FBLoginViewDelegate>
#property (weak, nonatomic) IBOutlet FBLoginView *loginButton;
#property (retain, nonatomic) NSString *id;
#property (retain, nonatomic) NSString *first_name;
#end
Create FBID, FBUSER properties in the required viewcontroller classes.Then write a method to create a shared instance of the view controller in the view controller class
+ (instancetype)sharedInstance {
static MyViewController *instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
This method will return a shared instance of MyViewController class. This is a static object.
MyViewController *myViewController = [MyViewController sharedInstance];
set your properties as myViewController.fbid = yourvalue or myViewController.first_name = yourvalue
You have to implement this shared instance method in all of your view controllers. So that you can create static objects and set a not static property as static
Here's my understanding of the view controller setup.
----- FaceBook Login VC
|
--> TabBarController --|----- VC1
|
|------VC2
|
------VC3
If the diagram looks right and you are trying to pass data between FaceBookLogin and VC -1, V-2 and VC -3.
You can do this by creating a subclass of TabBar Controller. In your subclass declare two properties for FBID and FBUSER.
If the use successfully logs in using "FaceBook Login" page, then set these properties in the custom tabBar controller.
You can now access these properties from any VC that is part of the tabbar controller.
Let me know if you need to see some code or need more detailed explanation.
Related
I'd like to trigger a message from viewController to another viewController.
And I coded like below, but viewController didn't call delegate.
I want to call delegate without stroyboard. I just want to send a message to another viewController.
viewController2.h
#protocol ViewController2Delegate;
#interface ViewController2 : UIViewController
#property (nonatomic, weak) id<ViewController2Delegate> delegate;
#end
#protocol ViewController2Delegate <NSObject>
- (void)showSomethingByDelegate;
#end
viewController2.m
#import "ViewController2.h"
#interface ViewController2 ()
#end
#implementation ViewController2
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (IBAction)buttonPressed:(id)sender {
[self.delegate showSomethingByDelegate];
}
#end
viewController.m
#import "ViewController.h"
#import "ViewController2.h"
#interface ViewController ()
<ViewController2Delegate>
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
ViewController2 *vc2 = [[ViewController2 alloc] init];
vc2.delegate = self;
}
// Below method was not called by delegate.
- (void)showSomethingByDelegate {
NSLog(#"Button Was Pressed!!!");
}
#end
well let me show an example more simple.
File: firstVC.h
/* This define the protocol object,
you can write methods required or optional the diference is when
the protocol is used in a class, xcode show you a yellow warning with required methods
like UITableViewDelegate, UITextFieldDelegate... */
#protocol firstVCDelegate <NSObject>
#required
- (void)didMessageFromOtherViewController: (NSString *)messageStr;
#optional
- (void)didOtherMessageNotRequired: (NSString *)messageStr;
#end
/* This is the definition of first UIViewController */
#interface firstViewController : UIViewController
#end
/* This is the definition of second UIViewController object with
a property that is our protocol 'firstVCDelegate' */
#interface secondViewController : UIViewController
#property (nonatomic, weak) id <firstVCDelegate> firstVCDelegate;
- (void)executeDelegateProcess;
#end
File: firstVC.m
#import "firstVC.h"
#pragma mark - First UIViewController with delegate
#interface firstViewController() <firstVCDelegate>
#end
#implementation firstViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Creating the 'secondViewController' object with delegate on this class
secondViewController *svc = [secondViewController new];
// Assign the delegate class
[svc setFirstVCDelegate: self];
// Run the delegate logic
[svc executeDelegateProcess];
}
- (void)didMessageFromOtherViewController:(NSString *)messageStr
{
// Receiving the message from the instance of our protocol in the 'secondViewController' class
NSLog(#"MESSAGE #1: %#", messageStr);
}
- (void)didOtherMessageNotRequired:(NSString *)messageStr
{
// Receiving the message in optional method
NSLog(#"MESSAGE #2: %#", messageStr);
}
#end
#pragma mark - Second UIViewController
#implementation secondViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)setFirstVCDelegate:(id<firstVCDelegate>)firstVCDelegate
{
if (firstVCDelegate)
_firstVCDelegate = firstVCDelegate;
}
- (void)executeDelegateProcess
{
// This method is only for demo
// You can execute your delegate in the way you need to use
if (_firstVCDelegate) {
[_firstVCDelegate didMessageFromOtherViewController: #"Hello world, using the required method from secondViewController class"];
[_firstVCDelegate didOtherMessageNotRequired: #"Hello code using the optional method"];
}
}
#end
In your appDelegate.m in the method didFinishLaunchingWithOptions you can put this, and you need to #import "firstVC.h"
self.window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]];
self.window.autoresizesSubviews = YES;
[self.window makeKeyAndVisible];
[_window setRootViewController: [firstViewController new]];
Execute and see two logs messages, I hope I've helped :)
ViewController2 *vc2 = [[ViewController2 alloc] init];
This line of code is not doing what you think it is, this is creating a NEW instance of ViewController2 and storing it inside the variable vc2. At no point (based on your code) is this variable added to the navigation stack and displayed on screen.
Edit
Also as noticed by Holex, your vc2 variable will be removed from memory after the viewDidLoad is finished as you are not holding onto a reference of it. You would either need to create a property to hold onto it, or push it onto the navigation stack for the navigationController to hold onto it.
There are multiple ways to solve this issue:
Instead of creating a new viewController2, find a reference to the one already displayed on the screen (if it is on the screen).
If its not on the navigation stack, add vc2 to the navigation stack [self.navigationController pushViewController:vc2 animated:YES]; (assuming you have a navigation controller).
If not on the stack, and not intending to use a navigationController, present vc2 modally, such as [self presentViewController:vc2 animated:YES completion:nil];
MMTransitionAnimator pod file was installed. View while swiping up and down its working fine but its not dismiss view while tap on button.Please refer this link github.com/mojun/MMTransitionAnimator.How to dismiss view while clicked on button action.can anyone help me.
While presenting:
self.modalVC.delegate = self;
In ModalViewController that is presented make a delegate that:
#protocol ModalViewControllerDelegate <NSObject>
#optional
- (void)closeButtonPressed;
#end
#interface ModalViewController : UIViewController
#property (nonatomic, weak) id <ModalViewControllerDelegate> delegate;
#end
#implementation ModalViewController
- (void)btnCloseTapped {
[self.delegate closeButtonPressed];
}
#end
Then Implement that delegate in your presenting view controller like:
- (void)closeButtonPressed {
//Needs to play more..
_animator = [[MMTransitionAnimator alloc] initWithOperationType:MMTransitionAnimatorOperationNone fromVC:_modalVC toVC:self];
_animator.usingSpringWithDamping = 0.8f;
_animator.interactiveType = MMTransitionAnimatorOperationDismiss;
_containerView.alpha = 1;
_handleBarView.y = self.view.height - _handleBarView.height;;
[self.modalVC dismissViewControllerAnimated:YES completion:nil];
}
I am trying to detect tapping of another tab from within a view controller embedded in a tabbarcontroller using one of the tabbarcontroller's delegate methods. However, I am confused about whether those methods can be in the individual view controllers or whether they have to be in the uitabbarcontroller class. I would like to have them in the view controllers where I have access to all the properties and local variables of those VCs rather than in the tabbarcontroller class.
I am also confused about how to set the delegate.
In a tableview controller embedded in the tabbarcontroller, I have declared the delegate protocol and then included the following code. However, the method is not firing. Is it okay to put this delegate method in a VC and if so, how and where should I set the delegate to get it to fire?
- (void)tabBarController:(UITabBarController *)tabBarController
didSelectViewController:(UIViewController *)viewController
{
NSLog(#"DIDSELECTVC FIRED");
NSLog(#"controller class: %#", NSStringFromClass([viewController class]));
NSLog(#"controller title: %#", viewController.title);
if (viewController == tabBarController.moreNavigationController)
{
tabBarController.moreNavigationController.delegate = self;
}
}
As said Toru Furuya said better way to implement UITabBarControllerDelegate is inside subclass of UITabBarController itself.
If you want to use certain inner view controller as delegate use tabBarController property:
- (void)viewDidLoad {
[super viewDidLoad];
self.tabBarController.delegate = self;
}
You can use either individual ViewController or UITabBarController itself for delegate as long as it conforms to UITabBarControllerDelegate protocol.
I think it is more common to use UITabBarController itself (or another dedicated class) to UITabBarControllerDelegate than child ViewControllers because you can set delegate only one. But if you want to use individual ViewController, I hope this code will help you.
#implementation MyTabBarController : UITabBarController
- (id)initWithCoder:(NSCoder *)aCoder{
self = [super initWithCoder:aCoder];
if (self) {
MyTableViewController *controller = [[MyTableViewController alloc] init];
controller.tabBarItem = ...
_delegate = controller; //Set individual ViewController to UITabBarControllerDelegate
[self setViewControllers:#[controller] animated:YES];
}
return self;
}
#end
MyTableViewController is:
#interface MyTableViewController : UITableViewController<UITabBarControllerDelegate>
#end
#implementation MyTableViewController
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
//Handle tap event of UITabBarController
}
#end
I have used the Xcode tab bar controller template and am trying to detect when a user selects a tab in my tab bar controller. In AppDelegate.h I have:
#import <UIKit/UIKit.h>
#interface AppDelegate : UIResponder <UIApplicationDelegate, UITabBarControllerDelegate> {
UITabBarController *tabBarController;
}
#property (strong, nonatomic) UIWindow *window;
#property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
#end
and in AppDelegate.m I have:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
tabBarController.delegate = self;
return YES;
}
- (void)tabBarController:(UITabBarController *)tabBarController
didSelectViewController:(UIViewController *)viewController
{
NSLog(#"Selected tab bar button!");
}
I have not connected any outlets for the Tab Bar Controller scene listed in Main.storyboard because I couldn't figure out the right connection to make, if one is even necessary. I also haven't made any references to this delegate method in my FirstViewController or anywhere else, because the various ways I tried to do that didn't work. Could someone help me understand how to get this working?
You can add tab bar controller by selecting UIViewController(FirstViewController in your case) and choose Editor >> Embed In >> Tab Bar Controller.
Eliminate the UITabBarController *tabBarController; declaration in AppDelegate.h (line 4) and replace
tabBarController.delegate = self;
with
self.tabBarController.delegate = self;
in AppDelegate.m.
I have the delegate working as the data is being passed from the modal to the presenting view controller. But the presenting view controller isn't showing the data it receives from the modal. I looked at other posts and they say to use the delegate/protocol method, but don't explain how/why the presenting VC refreshes. I'm assuming my delegate is setup incorrectly. Otherwise, what is the method to refresh the data? I've checked and the viewWillAppear and viewDidAppear doesn't get called.
SCCustomerDetailVC.h (Presenting VC)
#import "SCCustomersVC.h"
#interface SCCustomerDetailVC : UIViewController <SCCustomersVCDelegate>
#property (atomic, strong) SCCustomer *customer;
#property (strong, nonatomic) IBOutlet UIButton *changeCustomerButton;
- (IBAction)changeCustomerButtonPress:(UIButton *)sender;
#end
SCCustomerDetailVC.m (Presenting VC)
- (IBAction)changeCustomerButtonPress:(UIButton *)sender
{
UINavigationController *customersNC = [self.storyboard instantiateViewControllerWithIdentifier:#"customersNC"];
SCCustomersVC *customersVC = (SCCustomersVC *)customersNC.topViewController;
customersVC.delegate = self;
[self presentViewController:customersNC animated:YES completion:nil];
}
//Protocol methods
- (void)passCustomer:(SCCustomer *)customer
{
self.customer = customer;
//At this point, self.customer has the correct reference
[self dismissViewControllerAnimated:YES completion:nil];
}
SCCustomersVC.h (Modal VC)
#import "SCCustomersVCDelegate.h"
#class SCCustomerDetailVC;
#interface SCCustomersVC : UIViewController <UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate>
#property (weak, nonatomic) id <SCCustomersVCDelegate> delegate;
#end
SCCustomersVC.m (Modal VC)
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
SCCustomer *customer = [self customerAtIndexPath:indexPath];
[self.delegate passCustomer:customer];
}
SCCustomersVCDelegate.h
#class SCCustomer;
#protocol SCCustomersVCDelegate <NSObject>
#optional
- (void)passCustomer:(SCCustomer *)customer;
#end
I think you're nearly there. EDIT - just learned here that viewWillAppear behavior is different in iOS>5. You still want view will appear to update your view with your model state, since it needs to do that on initial presentation.
And it's fine to call it from either your modal vc or from within the delegate method. So add code to viewWillAppear that updates the view with the view controller's model state...
// SCCustomerDetailVC.m
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// making up an IBOutlet called someLabel
// making up a model method (description) that returns a string representing your model
self.someLabel.text = [self.customer description];
}
Then either from the presented vc or the delegate, call viewViewWillAppear:
- (void)passCustomer:(SCCustomer *)customer
{
self.customer = customer;
[self viewWillAppear:YES];
[self dismissViewControllerAnimated:YES completion:^{}];
}
You should reload your UI after setting the "customer"
- (void)passCustomer:(SCCustomer *)customer
{
self.customer = customer;
//At this point, self.customer has the correct reference
[self dismissViewControllerAnimated:YES completion:^{
// reload your UI here or call a method which will reload your ui
// e.g. for tableView it will be [tableView reload];
}];
}