difference between appdelegate and delegate in viewcontroller - iphone

I want to integrate one sample code with (for example SampleCode project) my iPhone application .In the sample code in firstViewController is added in MainWindow.xib and linked to viewController created in the below code.
#interface SampleCodeAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
firstViewController *viewController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet firstViewController *viewController;
and viewController instantiated with initWithCoder and when firstView is appeared on tap of button Camera can be opened be calling OpenCamera method as in the below code.
//in firstViewController.mm file
- (id)initWithCoder:(NSCoder *)coder {
if (self = [super initWithCoder:coder]) {
}
[self initLocal];
return self;
}
//to open camera in SampleCode application
- (IBAction)OpenCamera {
UIApplication *app = [UIApplication sharedApplication];
SampleCodeAppDelegate* delegate = [app delegate];
UIViewController* uiViewCont = [delegate viewController];
((CCamera*)m_pCamera)->Camera(uiViewCont);
}
In my navigation based application (MyApplication) I want to call firstViewController of SampleCode with one of viewController MyApplicationViewControllerA directly without adding to MyApplicationAppDelegate.
So I want to if I am creating the delegate in MyApplicationViewControllerA viewController that should work as the appdelegate in SampleCode application.
I am not able to open the camera but after closing the camera I am not able to open any other view of MyApplication except MyApplicationViewControllerA.
I am trying pushViewController and modalViewController not able to render other View.
I am not confused about the delegate. So I want to know what is the difference between AppDelegate(in SampleCodeAppDelegate : NSObject <UIApplicationDelegate>) and delegate declared in other ViewContrller.

I am trying pushViewController and modalViewController not able to render other View.
answer:
If you are not able to show other view after camera overlay screen then I think you need to show other view by performing action on main thread using performSelectorOnMainThread
[self performSelectorOnMainThread:#selector(showOtherView) withObject:OtherViewControllerObj waitUntilDone:YES];
and in the showOtherView selector method first you need to confirm that you should push the viewconroller in the navigationconroll and if that is already pushed then you should try to show otherview using presentModalViewController like below code.
-(void)showOtherView{
[self.navigationController pushViewController:OtherViewControllerObj animated:YES];
[self presentModalViewController:OtherViewControllerObj animated:YES];
}
I think this should work.

Related

ViewController Not Rotating

I have been having issues forever with an app, and getting certain views to rotate.
I already know that no view in a tab bar controller can rotate, unless ALL are allowed to rotate. I also know that no view within a navigation controller can rotate unless the top most view is allowed to rotate.
I used IB mostly to setup my app.
In the MainWindow.xib I have the AppDelegate Object, Window, TabBarController, and then a separate UIViewController.
Within one of the tabs of the tab bar, I have an IBAction linked to a UIButton with the following code:
-(IBAction)stuff {
[self presentViewController:buletinss animated:YES completion:nil];
}
The view controller is declared in the header file as an IBOutlet, and is linked from that tab class to the UIViewController. In IB, I then set the class for that view controller to a UIViewController class I set up, and return YES to allow it to rotate.
However, it still will not rotate.
I thought that since it was not a part of the tab bar, and not pushed from a navigation controller, that it would be allowed to rotate, but I am having no luck. Please any help?
Here is full code:
First, the .h and .m for the view that has the button:
#import <UIKit/UIKit.h>
#interface BulletinViewController : UIViewController {
IBOutlet UIWebView *worship;
IBOutlet UIActivityIndicatorView *activity;
NSTimer *timer;
IBOutlet UIViewController *buletinss;
}
-(IBAction)stuff;
#property (nonatomic, retain) UIActivityIndicatorView *activity;
#end
and the .m
#import "BulletinViewController.h"
#implementation BulletinViewController
-(IBAction)stuff {
[self presentViewController:buletinss animated:YES completion:nil];
}
Now the .h and the .m of the view it is presenting
#import <UIKit/UIKit.h>
#interface TestBulletinViewController : UIViewController
#end
and the .m
#import "TestBulletinViewController.h"
#implementation TestBulletinViewController
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
return YES;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Try change this code
[self presentViewController:buletinss animated:YES completion:nil];
to
[self presentModalViewController:buletinss animated:YES];
UPD: in iOS 6 you must:
1)
Replace
[window addSubview:buletinss.view];
with
window.rootViewController = buletinss;
2)
Add this code lines
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscape;
}
It's hard to know what's going on without seeing your project. You're doing a very odd thing: why are you loading a view controller from a nib? You are saying:
IBOutlet UIViewController *buletinss;
Why? Why are you not explicitly instantiating a BulletinViewController and setting the ivar to that?
I'm betting that the problem is that in the nib, this object is not a BulletinViewController. It's probably just a generic UIViewController. Hence your BulletinViewController code is irrelevant; none of it ever runs. Instead, you've got a generic UIViewController that only rotates to portrait. But that's just a guess.

iOS: How to have a login-form showed?

I have the mainWindow.xib in my application with a TabController in it for my main-menu.
Now I want to have a Login-form for my application.
I added a View (LoginViewController) and show this view at beginning:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
// Add the tab bar controller's current view as a subview of the window
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
LoginViewController *lvc = [[LoginViewController alloc] initWithNibName:#"LoginViewController" bundle:nil];
lvc.delegate = self;
[self.tabBarController presentModalViewController:lvc animated:false];
[lvc release];
return YES;
}
Next I have my login-checks in the view, okay.
Now I try to dismiss the view after this.
For this I searched around and found the question here: present modal view controller
I add all things to my project, but getting a error in this code:
#import <UIKit/UIKit.h>
#interface Animexx3AppDelegate : NSObject <UIApplicationDelegate,
UITabBarControllerDelegate, LoginViewControllerDelegate>
{
UIWindow *window;
UITabBarController *tabBarController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
#end
Which means "cannot find protocol LoginViewControllerDelegate" in line 2/3.
Addition in the line "lvc.delegate = self" I get a warning that tells me "assigning to "id" from incompatible type "Animexx3AppDalagte".
What did Im wrong?
You need to import the header file where you declared the LoginViewControllerDelegate protocol. Most likely the LoginViewController.h file.
After struggling with this many times, we published an open source library called CLHoppingViewController which handles exactly this kind of scenarios.
So, in your case, you would do something like this to describe the start up flow:
UIViewController *loginViewController;
UIViewController *mainViewController;
if (user_not_logged_in) {
[self hopToViewController:loginViewController then:^{
[self hopToViewController:mainViewController then:nil];
}];
}
else {
[self hopToViewController:mainViewController then:nil];
}
The library can support much more advanced conditional sequences. For example, you can display a splash screen, conditionally show onboarding UX, etc.
There's a short tutorial here.

UITabbarControl with a login screen

any-body tried a scenario like, a login screen to show for the first time and after validation of username the application starts with uitabbar controller.
i tried with the application with uitabbar only. with the login screen put as first-view in tabbar controller, with "TabBarController.tabBar.hidden=TRUE;" but the view is getting distorted (the space for tabbar is still empty) and here some one can help me in getting the view properly displayed?
thanks,
abhayadev s
another possibility is to show the login viewController as a modal viewController. Modal VC hide the tabbar.
Create another viewController (e.g. LoginViewController). In your AppDelegate in applicationDidFinishLaunching: add (isLogged is just for exemple):
if (self.isLogged) {
[window addSubview:self.tabBarViewController.view];
} else {
LoginViewController *loginVC = [[LoginViewController alloc] initWithNibName:#"login" bundle:nil];
[window addSubview:loginVC.view];
}
And you should call a method when login is successful that removes loginVC view and add tabBarController.view on the window.
It's no more complicated than that.
The application only needs to use the LoginViewController until the user is authenticated, signed up, linked with FB or whatever, and then that LoginViewController should be released as it is no longer needed. This solution might look like overkill but I think it extends well. Here's how I do it, and in my case I just had a Splash screen that displayed some information and then the user goes to the main part of the application:
First I actually made a simple protocol which I can implement in my MainAppDelegate.m file, called SplashDelegate:
//SplashDelegate.h
#protocol SplashDelegate <NSObject>
- (void) splashExit : (id) sender;
#end
Then my MainAppDelegate implements that. First after the application launches, self.window's rootViewController will point to my SplashViewController, then after that is closed, the MainViewController (in OP's case his TabViewController) will be instantiated.
Here's the important part of my main app delegate h file:
#import "SplashDelegate.h"
#class MainViewController;
#class SplashViewController;
#interface MainWithLoginPageAppDelegate : NSObject <UIApplicationDelegate, SplashDelegate> {
MainViewController *_viewController;
UIWindow *_window;
SplashViewController *_splashViewController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet MainViewController *viewController;
#property (nonatomic, retain) IBOutlet SplashViewController *splashViewController;
And the important part of the m file:
#import "MainWithLoginPageAppDelegate.h"
#import "MainViewController.h"
#import "SplashViewController.h"
#implementation MainWithLoginPageAppDelegate
#synthesize window=_window;
#synthesize viewController=_viewController;
#synthesize splashViewController = _splashViewController;
- (void) splashExit : (id) sender
{
_viewController = [[MainViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
self.window.rootViewController = self.viewController;
[_splashViewController release];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//initialize my splash controller
_splashViewController = [[SplashViewController alloc] initWithNibName:#"SplashViewController" bundle:nil];
self.splashViewController.parentDelegate = self;
self.window.rootViewController = self.splashViewController;
[self.window makeKeyAndVisible];
return YES;
//note that _viewController is still not set up... it will be setup once the login phase is done
}
Then all you need in the SplashViewController (or LoginViewController) is your login test and your property for the parentDelegate. Inside of SplashViewController.h I make my parentDelegate an instance variable, as id <SplashDelegate> _parentDelegate. Another good idea would be to extend the protocol above to offload the responsibility of checking the user's login so that you're not checking the login inside of the view controller class.
Edit: Inside of the LoginViewController, then, you can call [self.parentDelegate splashExit:self], and modify the idea above to include your login checks as well.
Hope this is helpful to someone!
Have the login page in the firstview controller.Add the tabbar to the window only after navigating to the second view controller.Thats it.
All the best.

Showing login view controller before main tab bar controller

I'm creating an iPad app with a tab bar controller that requires login. So on launch, I want to show a LoginViewController and if login is successful, then show the tab bar controller. This is how I implemented an initial test version (left out some typical header stuff, etc)...
AppDelegate.h:
#interface AppDelegate_Pad : NSObject
<UIApplicationDelegate, LoginViewControllerDelegate> {
UIWindow *window;
UITabBarController *tabBarController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
#end
AppDelegate.m:
#implementation AppDelegate_Pad
#synthesize window;
#synthesize tabBarController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
LoginViewController_Pad *lvc = [[LoginViewController_Pad alloc] initWithNibName:#"LoginViewController_Pad" bundle:nil];
lvc.delegate = self;
[window addSubview:lvc.view];
//[lvc release];
[window makeKeyAndVisible];
return YES;
}
- (void)loginViewControllerDidFinish:(LoginViewController_Pad *)loginViewController {
[window addSubview:tabBarController.view];
}
- (void)dealloc {...}
#end
LoginViewController_Pad.h:
#protocol LoginViewControllerDelegate;
#interface LoginViewController_Pad : UIViewController {
id<LoginViewControllerDelegate> delegate;
}
#property (nonatomic, assign) id <LoginViewControllerDelegate> delegate;
- (IBAction)buttonPressed;
#end
#protocol LoginViewControllerDelegate
-(void)loginViewControllerDidFinish:(LoginViewController_Pad *)loginViewController;
#end
LoginViewController_Pad.m:
#implementation LoginViewController_Pad
#synthesize delegate;
...
- (IBAction)buttonPressed
{
[self.view removeFromSuperview];
[self.delegate loginViewControllerDidFinish:self];
}
...
#end
So the app delegate adds the login view controller's view on launch and waits for login to call "did finish" using a delegate. The login view controller calls removeFromSuperView before it calls didFinish. The app delegate then calls addSubView on the tab bar controller's view.
If you made it up to this point, thanks, and I have three questions:
MAIN QUESTION: Is this the right way to show a view controller before the app's main tab bar controller is displayed? Even though it seems to work, is it a proper way to do it?
If I comment out the "lvc release" in the app delegate then the app crashes with EXC_BAD_ACCESS when the button on the login view controller is pressed. Why?
With the "lvc release" commented out everything seems to work but on the debugger console it writes this message when the app delegate calls addSubView for the tab bar controller: Using two-stage rotation animation. To use the smoother single-stage animation, this application must remove two-stage method implementations. What does that mean and do I need to worry about it?
UPDATE:
As suggested by lucius, changed it to modally show the login view controller from the app delegate. This appears to be a cleaner solution. Code changed as follows...
AppDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[window addSubview:tabBarController.view];
[window makeKeyAndVisible];
LoginViewController_Pad *lvc = [[LoginViewController_Pad alloc] initWithNibName:#"LoginViewController_Pad" bundle:nil];
lvc.delegate = self;
[self.tabBarController presentModalViewController:lvc animated:NO];
[lvc release];
return YES;
}
-(void)loginViewControllerDidFinish:(LoginViewController_Pad *)loginViewController {
[self.mainTabBarController dismissModalViewControllerAnimated:NO];
}
LoginViewController_Pad.m:
- (IBAction)buttonPressed
{
//do NOT removeFromSuperview, delegate will dismiss
//[self.view removeFromSuperview];
[self.delegate loginViewControllerDidFinish:self];
}
I'd use the method to present the view controller modally instead of adding it to the window. That will make it properly retain the controller. The debugger message has to do with certain autorotation methods being implemented in your class. You can ignore it for now.

TabBar application, moreNavigationBar and nibs with navigationBars

I have a TabBar application with several nibs, most with a NavBar. It works pretty well, except for the "views" that are inside the "More" section of the tabBar.
As expected, it will put a NavBar to return to the "More" list, as well as the NavBar i've placed in the nib.
I've tried to remove the view controllers from the moreNavigationBar and put the top controller from my nib's navBar, but I get and extra view from somewhere:
- (void)viewDidLoad {
TestAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
UITabBarController *ctrl = appDelegate.rootController;
UINavigationController *navCtrl = ctrl.moreNavigationController;
[navCtrl popToRootViewControllerAnimated: NO];
[navCtrl pushViewController: navController.topViewController animated: YES];
navController = navCtrl;
[super viewDidLoad];
}
My AppDelegate:
#interface TestAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
UITabBarController *rootController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UITabBarController *rootController;
The MainWindow nib is that of a Window-based project with a TabBarController, linked to the rootController in my app delegate.
The other nibs have a view + navigationController and I have a UITableViewController subclass as my Root View Controller.
If I could get this to work it wouldn't still solve my problem, because I want to allow the user to place this anywhere in the tabBar, so, I must have some way of knowing if there's a navigationBar.
So, my question is, how do you know if there's a navigationBar (in this case, if the tabBar's navigationBar is being shown) and, if so, how do I get my navigationController to "become" the tabBar's navigationController?
Or, if you have another idea on how to solve this problem, i'd also be appreciated :)
The recommendation from apple is that you have the TabBar controller contain the Navigation controllers and not the other way around. I have a setup more or less like this, and I have the More tab hold a Nav controller, basically like this:
#interface SomethingNavViewController : UIViewController {
UIView* aview;
UINavigationController *navigationController;
}
#property (nonatomic, retain) IBOutlet UIView *aview;
#property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
#end
In the NIB, I have a separate Nav controller in the view of the more panel, I haven't replaced the tab bar item's view with a nav controller view, I've just added a Nav controller to the view.
In my implementation file, I have:
- (void)viewDidLoad {
[super viewDidLoad];
[[self view] addSubview:[navigationController view]];
SomeOtherController *aController = [[[SomeOtherController alloc ] initWithNibName:#"SomeOtherController" bundle:nil ] autorelease];
aController.title = #"Artwalks";
// lots of application logic here.
[self.navigationController pushViewController:aController animated:YES];
[self.navigationController setDelegate:self];
}
One key thing about this is that I have implemented the navigationController's delegate method, which is really handy when you're just inserting the nav controller. I found when I didn't do this, my views don't get viewDidAppear messages, so I implemented the protocol and added this method:
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if ([viewController respondsToSelector:#selector(viewDidAppear:)]) {
[viewController viewDidAppear:animated];
}
}
and that solved a variety of my lingering problems.
Anyway, I hope this answer gave you the detail you needed. IF it didn't, please give more details about your question. I'm not quite sure what but I get and extra view from somewhere met, but it sounds like something I encountered before I found this solution.