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.
Related
I'm having a problem using the Facebook SLComposeViewController in a UIView. The problem I'm having is because I have a UIView and not a UIViewController that I'm inheriting from.
I've imported:
#import <Social/Social.h>
#import <Accounts/Accounts.h>
and am trying to present the Facebook sharing using:
SLComposeViewController *controllerSLC = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
[controllerSLC setInitialText:#"First post from my iPhone app"];
[controllerSLC addURL:[NSURL URLWithString:#"http://www.test.com"]];
[controllerSLC addImage:[UIImage imageNamed:#"test.jpg"]];
[self presentViewController:controllerSLC animated:YES completion:Nil];
It's the last line it won't present the view because I'm inheriting from UIView and not UIVIewController I'm not sure how to fix this. I just want to share an image.
thanks for any help.
UIViews cannot present view controllers. You'll need to set up a way to call back to the UIViewController that is presenting to your UIView.
A common way would be to make create a delegate on your view. When something happens on that view, the delegate method is called which messages the view controller that implements your delegate methods. From there, you can present the view controller from your parent view controller.
In your view's .h file:
#protocol YourUIViewDelegate <NSObject>
- (void)theDelegateMethod;
#end
#interface YourUIView : UIView
#property (assign, nonatomic) id<YourUIViewDelegate> delegate;
In your view's .m file (I'm assuming there's a button press or some other action method that gets called where you want to present this view controller):
- (void)buttonTapped:(id)sender
{
[self.delegate theDelegateMethod];
}
In the view controller .h that is presenting the delegate method:
#interface ThePresentingViewController <YourUIViewDelegate>
In that view controller's .m file:
- (void)theDelegateMethod
{
// All of the SLComposeViewController code
}
Don't forget to set the view's delegate to the view controller within the presenting view controller.
Is it possible to present a modal view from a UIView or a UIWindow in the same .xib?
here is my code:
#interface MyViewController : UIViewController <UIWebViewDelegate> {
IBOutlet UIVIew *myView
}
#property (nonatomic, retain) UIView *myView;
- (void)somefunction;
And my function:
- (void)somefunction {
//here i need to make my view1 gets presented by a modal view style.
}
You need to add IBOutlets for your views. In your MyViewController.h file:
...
IBOutlet UIView *firstView;
IBOutlet UIView *secondView;
...
Then you connect the outlets using Interface Builder (or Xcode 4). After that, in your implementation file you manually hide or show the view that you want.
PresenterViewController.m:
- (void)ShowSecondView{
//Initialize the view controller
MyViewController *modalView = [[MyViewController alloc] initWithNibNamed:#"MyViewController" bundle:nil];
//Hide or show whatever view(s) you want
[modalView.firstView setHidden:YES];
[modalView.secondView setHidden:NO];
//Present the view controller modally
[self presentModalViewController:modalView animated:YES];
//Don't forget memory management!
[modalView release];
}
You may need to tweak this code a little bit, but this is the general idea.
I am starting a multiview app with two views: NewGame and Players. I thought I was setting everything up properly, but apparently not.
MainViewController.h
#import <UIKit/UIKit.h>
#class NewGame; #class Players;
#interface MainViewController : UIViewController {
IBOutlet NewGame *newGameController;
IBOutlet Players *playersController;
}
-(IBAction) loadNewGame:(id)sender;
-(IBAction) loadPlayers:(id)sender;
-(void) clearView;
#end
MainViewController.m
#import "MainViewController.h"
#import "NewGame.h"
#import "Players.h"
#implementation MainViewController
-(IBAction) loadNewGame:(id)sender {
[self clearView];
[self.view insertSubview:newGameController atIndex:0];
}
-(IBAction) loadPlayers:(id)sender {
[self clearView];
[self.view insertSubview:playersController atIndex:0];
}
-(void) clearView {
if (newGameController.view.superview) {
[newGameController.view removeFromSuperview];
} else if (playersController.view.superview) {
[playersController.view removeFromSuperview];
}
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[self loadNewGame:nil];
[super viewDidLoad];
}
A couple of images...
http://i.stack.imgur.com/GwXMa.png
http://i.stack.imgur.com/XHktH.png
Views are objects that represent what appears on screen. View controllers are objects that perform application logic relating to those views. A view hierarchy is a collection of views. You are attempting to add a view controller to a view hierarchy as if it were actually a view.
Roughly speaking, you should have one view controller for every "screen" of your app. This view controller can manage any number of views. Its main view is accessible through its view property.
A quick fix to get your application operational would be to add the main view of your view controllers instead of the view controllers themselves. So, for example, this:
[self.view insertSubview:playersController atIndex:0];
...would become this:
[self.view insertSubview:playersController.view atIndex:0];
Having said that, this is not a good solution long-term, and you should investigate a more structured way of organising transitions from view controller to view controller. UINavigationController is a good option for beginners.
I suppose playerController is view controller. Then add
[self.view addSubview: playerController.view];
OR if not then subclass them for UIView
NewGame and Players both need to subclass UIView. If they're ViewControllers, not UIViews, you'll need to use newGameController.view instead of newGameController.
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.
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.