I am trying to call my shouldSelectViewController Delegate function. But it doesnt seem to work.
I did the following, but still the function doesnt get called
.h
#interface myAppDelegate : UIResponder <UIApplicationDelegate, UITabBarControllerDelegate>
#property (strong, nonatomic) UIWindow *window;
#end
.m
#implementation TakeFiveCameraAppDelegate
#synthesize window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;
tabBarController.delegate = (id)self;
return YES;
}
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
NSLog(#"test");
return YES;
}
#end
I am not sure what am I missing here.
add in viewDidLoad
[self setDelegate:self];
Related
I have three UIViewcontroller, namely ViewController, BViewController and CViewController, ViewController is RootViewController from UINavigationController,
I'm pushing from ViewController -> BViewController -> CViewController, through button action.
I have declared protocol in CViewController. This protocol method is working fine for BViewController, but I don't understand how to make work its delegate method in ViewController.
I had created an object of CViewController in View Controller, then declared self for that delegate, though its not working, Below is my code. Please help me. Where I'm doing wrong here !
My Root View Controller, namely ViewController
#import "ViewController.h"
#import "BViewController.h"
#import "CViewController.h"
#interface ViewController ()<testDelegates>
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
CViewController *cVC = [self.storyboard instantiateViewControllerWithIdentifier:#"CViewController"];
cVC.mydelegate = self;
}
- (IBAction)nextAction:(id)sender {
BViewController *bViewC = [self.storyboard instantiateViewControllerWithIdentifier:#"BViewController"];
[self.navigationController pushViewController:bViewC animated:YES];
}
-(void)TestMethod{
NSLog(#" Its NOT Working");
}
My Second View Controller, Namely BViewController
#import "BViewController.h"
#import "CViewController.h"
#interface BViewController ()<testDelegates>
#end
#implementation BViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (IBAction)bNextAction:(id)sender {
CViewController *cVC = [self.storyboard instantiateViewControllerWithIdentifier:#"CViewController"];
// cVC.mydelegate = self;
[self.navigationController pushViewController:cVC animated:YES];
}
-(void)TestMethod{
NSLog(#" Its Working If I uncomment to cVC.mydelegate = self");
}
And my third View Controller, Where i Declared a protocol in .h file, namely CViewController
#import <UIKit/UIKit.h>
#protocol testDelegates <NSObject>
-(void)TestMethod;
#end
#interface CViewController : UIViewController
#property (weak) id <testDelegates> mydelegate;
#end
And in .m file
#import "CViewController.h"
#interface CViewController ()
#end
#implementation CViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (IBAction)cNextAction:(id)sender {
[self.mydelegate TestMethod];
}
You create class and this class destroying after you leave viewDidLoad method.
- (void)viewDidLoad {
[super viewDidLoad];
CViewController *cVC = [self.storyboard instantiateViewControllerWithIdentifier:#"CViewController"];
cVC.mydelegate = self;
}
As I understand you need to perform some methods in the ViewController from the CViewController.
You can pass viewController as delegate from the BViewController and them past it to the CViewController.
Or you can use code like this:
- (IBAction)cNextAction:(id)sender {
id< testDelegates > delegate = self.navigationController.viewControllers[0];
if([delegate conformsToProtocol:#protocol(testDelegates)])
{
[delegate TestMethod];
}
}
This is no best way but it's will be work.
Try this
self.delegate = self.navigationController.viewControllers[0];
You need to declare a another Protocol into BViewController class.
Please follow below steps.
Step 1: BViewController.h
#protocol testDelegates2 <NSObject>
-(void)TestMethod2;
#interface BViewController : UIViewController
#property (weak) id <testDelegates> mydelegate;
#end
#implementation CViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (IBAction)cNextAction:(id)sender {
[self.mydelegate TestMethod2];
}
Step 2. In ViewController class conform Protocol
#interface ViewController ()<testDelegates>
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
CViewController *cVC = [self.storyboard instantiateViewControllerWithIdentifier:#"CViewController"];
cVC.mydelegate = self;
}
- (IBAction)nextAction:(id)sender {
BViewController *bViewC = [self.storyboard instantiateViewControllerWithIdentifier:#"BViewController"];
cVC.mydelegate = self; //important line
[self.navigationController pushViewController:bViewC animated:YES];
}
-(void)TestMethod2{
NSLog(#"Final Output");
}
If Your are trying to set Delegate of CViewController to ViewController then
try putting
self.mydelegate = self.navigationController.viewControllers[0]
on viewDidLoad method of CViewController.
Else you are Trying to make ViewController And BViewController both be Delegate of CViewController then this is not possible like this, as Delegate of a Object Can only be unique. This means the delegate is simply a variable which holds reference of object and as you know value to a variable can be unique at a instance of time.
So If you are willing to do some task on both Viewcontroller and BViewController then use notification pattern. See apple doc here
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'm struggling to prefill a textfield when I launch the app with my url scheme. When the app is launched without already being in memory, the value is not being set (or I think overruled by viewDidLoad or similar).
The boiled down path I'm taking looks like this:
// AppDelegate.m
-(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
UINavigationController *nav = (UINavigationController *)[[application keyWindow] rootViewController];
MainViewController *main = (MainViewController *)[nav topViewController];
[main setLabelText:#"this should be shown on screen"];
return YES;
}
With a ViewController sitting in a UINavigationController
// MainViewController.m
#interface MainViewController ()
#property (weak, nonatomic) IBOutlet UILabel *someLabel;
#end
#implementation MainViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.someLabel.text = #"this is actually shown on screen";
}
- (void)setLabelText:(NSString *)text
{
self.someLabel.text = text;
}
#end
So the label shows "this is actually shown on screen", not the text I set in AppDelegate. When setting breakpoints its fairly obvious why, I think, because viewDidLoad is called after setLabelText.
Is there a more robust path to prefilling text fields from a custom url scheme I'm missing?
Try this:
-(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
UINavigationController *nav = (UINavigationController *)[[application keyWindow] rootViewController];
MainViewController *main = (MainViewController *)[nav topViewController];
main.view;
[main setLabelText:#"this should be shown on screen"];
return YES;
}
The view is lazy loaded so it will load the first time it is needed.
The reason for this is that setLabelText: is called from the app delegate prior to the view controller's viewDidLoad method being called. What you'll need to do is keep a copy of the string in a property on the view controller then set that on the the label in viewDidLoad:
Header:
#interface MainViewController
#property (nonatomic, copy) NSString *stringToSet;
#end
Implementation:
#implementation MainViewController
- (void)viewDidLoad {
[super viewDidLoad];
if (self.stringToSet) {
self.someLabel.text = self.stringToSet;
} else {
self.someLabel.text = #"Some default string";
}
}
#end
App Delegate:
-(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
UINavigationController *nav = (UINavigationController *)[[application keyWindow] rootViewController];
MainViewController *main = (MainViewController *)[nav topViewController];
[main setStringToSet:#"this should be shown on screen"];
return YES;
}
Does anyone know of a way to have a UITabBarButton that, rather than segueing to another view controller, will perform another function, e.g. call a method?
My iPad app utilises a tab bar but the client wants the right-most button to perform a check for updates on a server; however I can't seem to to figure out how to have a button that won't switch views when pressed. I tried deleting the segue but that removes the button as well.
-EDIT-
screenshot and code snippet added for clarity. The tab labelled Sync is the one I want not to open a viewController:
AppDelegate.h:
#interface AppDelegate : UIResponder <UIApplicationDelegate, UITabBarControllerDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) UIViewController *viewController;
#end
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[self.window makeKeyAndVisible];
UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;
tabBarController.delegate = (id)self;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(applicationDidTimeout:) name:kApplicationDidTimeoutNotification object:nil];
return YES;
}
and:
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
NSLog(#"vc = %#", viewController);
return YES;
}
Look at the UITabBarControllerDelegate method :
– tabBarController:shouldSelectViewController:
If selectViewController == your last tab bar, return NO and perform others actions
EDIT :
Look at the example I've made :
AppDelegate.h
#interface ISAppDelegate : UIResponder <UIApplicationDelegate, UITabBarControllerDelegate>
#property (strong, nonatomic) UIWindow *window;
#end
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController;
tabBarController.delegate = (id)self;
return YES;
}
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
// here check if "viewController" is your last tab controller, then return NO and perform some actions you need
if (viewController = self.lastTabController) {
// do some actions
return NO;
}
return YES;
}
I've been banging my head against this all day, it seems like something simple but I can't figure it out.
I've got an iOS app that I created using the "View-based Application" template in XCode. Here is essentially the code I have:
AppDelegate.h:
#import <UIKit/UIKit.h>
#interface AppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
MainViewController *viewController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet MainViewController *viewController;
#end
AppDelegate.m:
#import "AppDelegate.h"
#import "MainViewController.h"
#implementation AppDelegate
#synthesize window, viewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self.window addSubview:viewController.view];
[self.window makeKeyAndVisible];
return YES;
}
- (void)dealloc {
[viewController release];
[window release];
[super dealloc];
}
#end
MainViewController.h:
#import <UIKit/UIKit.h>
#interface MainViewController : UIViewController {
}
-(IBAction) button:(id)sender;
#end
MainViewController.m:
#import "MainViewController.h"
#import "ModalViewController.h"
#implementation MainViewController
...
-(IBAction) button:(id)sender {
ModalViewController *mvc = [[[ModalViewController alloc] initWithNibName:NSStringFromClass([ModalViewController class]) bundle:nil] autorelease];
[self presentModalViewController:mvc animated:YES];
}
#end
There's nothing of interest in the ModalViewController.
So the modal view should display when the button is pressed. When I press the button, it hangs for a second then crashes back to the home screen with no error message.
I am stumped, please show me what I'm doing wrong!
There's nothing of interest in the ModalViewController.
Although there may not be anything of interest, there could still be something causing the problem.
Does your View Controller override the function loadView?
A problem that has got me a few times is if you don't call [super loadView]; first in your overriden loadView method. Not doing this causes a crash when moving into that View Controller.
Good luck in trying to solve this one!
N