iOS switching view controllers depending on the device orientation - iphone

I'm developing an Augmented Reality application, everything worked properly till now that I need two different kind of visualization (AR and Map) depending on the device orientation. In particular the application should use the landscapeViewController when the device is in landscape mode while it should use another controller (named faceUpViewController ) when the device's orientation is "face up". I tried doing it with two simple view controllers and it works fine. The problem happens when the landscapeViewController uses the AR controller. The view is completely white and I don't understand why. Both the two controllers are "contained" by a Root View Controller. I'm doing everything by coding so without nib files. Here is the code:
RootViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(deviceOrientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
}
- (void)deviceOrientationDidChange:(NSNotification *)notification{
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
if (orientation == UIDeviceOrientationLandscapeLeft) {
if (self.landscapeViewController.view.superview == nil) {
if (self.landscapeViewController == nil) {
LandscapeViewController *lvc = [[LandscapeViewController alloc] init];
self.landscapeViewController = lvc;
[lvc release];
}
[self.faceUpViewController.view removeFromSuperview];
[self.view addSubview:self.landscapeViewController.view];
}
}
if (orientation == UIDeviceOrientationFaceUp) {
if (self.faceUpViewController.view.superview == nil) {
if (self.faceUpViewController == nil) {
FaceUpViewController *fvc = [[FaceUpViewController alloc] init];
self.faceUpViewController = fvc;
[fvc release];
}
[self.landscapeViewController.view removeFromSuperview];
[self.view addSubview:self.faceUpViewController.view];
}
}
}
#end
LandscapeViewController.m
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView
{
UIView *landscapeView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
landscapeView.backgroundColor = [UIColor yellowColor];
self.view = landscapeView;
[landscapeView release];
ARController *arC = [[ARController alloc] initWithViewController:self];
arC.landscapeViewController = self;
self.arController = arC;
[arC release];
}
//When the view appear present the camera feed
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[_arController presentModalARControllerAnimated:NO];
}
FaceUpViewController.m
- (void)loadView
{
UIView *faceUpView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1024, 768)];
faceUpView.backgroundColor = [UIColor blueColor];
self.view = faceUpView;
[faceUpView release];
}
ARController.m Very simple version
- (id) initWithViewController:(UIViewController *)theView{
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
self.rootController = theView;
//Retrieve screen bounds
CGRect screenBounds = [[UIScreen mainScreen] bounds];
UIView *overlaidView = [[UIView alloc] initWithFrame: screenBounds];
self.overlayView = overlaidView;
[overlaidView release];
self.rootController.view = overlayView;
// Initialise the UIImagePickerController
UIImagePickerController *picker= [[UIImagePickerController alloc] init];
self.pickerController = picker;
[picker release];
self.pickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
self.pickerController.cameraViewTransform = CGAffineTransformScale(
self.pickerController.cameraViewTransform, 1.0f, 1.12412f);
self.pickerController.showsCameraControls = NO;
self.pickerController.navigationBarHidden = YES;
self.pickerController.cameraOverlayView = _overlayView;
}
return self;
}
- (void)presentModalARControllerAnimated:(BOOL)animated{
[self.rootController presentModalViewController:[self pickerController] animated:animated];
self.overlayView.frame = self.pickerController.view.bounds;
}
#end
I say again that I'm doing everything by coding thereby without nib files.
I really appreciate any advice!
Thanks

The primary problem with adding and removing your "child" view controllers' views as you've done here is that the view controller life cycle methods (viewWillAppear:, viewDidAppear:, etc.) won't ever get called on your child view controllers. Containers like UINavigationController and UITabBarController have always known how to delegate methods like these appropriately to their children, but UIViewController didn't officially support the ability to nest view controllers under your own custom container before iOS 5. It was possible, but it took a lot more work to do it right.
If you want to stick with the approach of adding and removing subviews, you have two options:
Require iOS 5+, and call addChildViewController:, removeFromParentViewController,
transitionFromViewController:toViewController:duration:options:animations:completion:,
willMoveToParentViewController:, and
didMoveToParentViewController: as described in the Implementing a Container View Controller section of the UIViewController Class Reference.
To support older iOS versions, you'll have to override many of the methods of the UIViewController class and delegate those calls manually to your child view controllers to make them behave as expected. I'd pay particular attention to the sections titled, "Responding to View Events", and "Responding to View Rotation Events" in the UIViewController Class Reference.
A different approach for pre-iOS 5 support is to present your child view controllers using presentModalViewController:animated: rather than adding their views as subviews to a container. Apple describes this approach in the View Controller Programming Guide for iOS under the section, Creating an Alternate Landscape Interface. The advantage of this approach is that your child view controllers are officially supported as first-class members of the view controller hierarchy, so UIKit will automatically manage their life cycles appropriately. You won't have to override and delegate all those methods manually.

You might want to try getting your acceptance rate up a little bit - more people would be willing to help you.
Anyway, wild guess: in your root controller, try putting the contents of
deviceOrientationDidChange
into
deviceOrientationWillChange.

Related

UIImagePickerControllerCameraDeviceFront works every other time

This question is very similar to an existing question asked here UIImagePickerControllerCameraDeviceFront only works every other time I tried the solution presented but it didn't work for me
I have a simplest of a project with two view controllers. In the blue one I am displaying a small UIView with a UIImagePickerController in it. NOTE: I am displaying front facing camera when app is launched.
I hit the next button and go to orange view controller and when I hit the back button and come back to blue view controller the UIImagePickerController flips from Front to rear. I guess the reason is that it thinks its busy and moves to the rear cam. If I keep moving back and forth between the view controllers the camera keeps flipping front, back, front, back, front, back...
Here is my code and screenshots, what am I doing wrong?
In my *.h
#import <UIKit/UIKit.h>
#interface v1ViewController : UIViewController <UIImagePickerControllerDelegate>
{
UIImagePickerController *picpicker;
UIView *controllerView;
}
#property (nonatomic, retain) UIImagePickerController *picpicker;
#property (nonatomic, retain) UIView *controllerView;
#end
In my *.m file (This code is only used when blue colored view controller is displayed)
#import "v1ViewController.h"
#import <MobileCoreServices/UTCoreTypes.h>
#implementation v1ViewController
#synthesize picpicker;
#synthesize controllerView;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
picpicker = [[UIImagePickerController alloc] init];
picpicker.delegate = self;
picpicker.mediaTypes = [NSArray arrayWithObjects:(NSString *)kUTTypeImage, nil];
picpicker.sourceType = UIImagePickerControllerSourceTypeCamera;
picpicker.cameraDevice = UIImagePickerControllerCameraDeviceFront;
picpicker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
picpicker.showsCameraControls = NO;
picpicker.navigationBarHidden = NO;
picpicker.wantsFullScreenLayout = NO;
controllerView = picpicker.view;
[controllerView setFrame:CGRectMake(35, 31, 250, 250)];
controllerView.alpha = 0.0;
controllerView.transform = CGAffineTransformMakeScale(1.0, 1.0);
[self.view addSubview:controllerView];
[UIView animateWithDuration:0.3
delay:0.0
options:UIViewAnimationOptionCurveLinear
animations:^{
controllerView.alpha = 1.0;
}
completion:nil
];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[picpicker dismissModalViewControllerAnimated:YES];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
[picpicker dismissModalViewControllerAnimated:YES];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
} else {
return YES;
}
}
#end
You are dismissing the controller in both the viewDidDisappear and viewWillDisappear methods.
That could be the cause of your problem.
Although I do not have a device with a camera available right now to verify this, it seems that you're not dismissing the pickerview controller correctly. The documentation states that you should call dismissModalViewControllerAnimated: on the parent controller in order to dismiss the picker (though, calls to presented controllers will propagate to presenters - so this is not the problem), but in your case you're not displaying the controller modally in the first place so it will not work.
What I would try in this case is to release the picker instead (if not under ARC) and set it to nil (instead of calling [picpicker dismissModalViewControllerAnimated:YES];).
PS. In fact, it seems that there is a bigger problem with your design. Since each button is set to present the other party modally you are not dismissing any of the controllers ever. The controllers just keep stacking on each other. You should either consider to embed them in a navigation controller and have it handle the hierarchy or just set dismissModalViewControllerAnimated: (dismissViewControllerAnimated:completion: on iOS5+) as the action of the second controller's button instead of a modal segue.
This is a very simple issue. I don't know why this happens exactly, but it seems that UIImagePickerController was designed to recreated each time it's needed instead of keeping any reference to it, which seems logical if you think about it. Basically, you need to recreate and reconfigure your picker each time. Below I've pasted some code to give an image of what I mean.
Simple solution:
- (UIImagePickerController *)loadImagePicker {
UIImagePickerController *picpicker = [[UIImagePickerController alloc] init];
picpicker.delegate = self;
picpicker.mediaTypes = [NSArray arrayWithObjects:(NSString *)kUTTypeImage, nil];
picpicker.sourceType = UIImagePickerControllerSourceTypeCamera;
picpicker.cameraDevice = UIImagePickerControllerCameraDeviceFront;
picpicker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
picpicker.showsCameraControls = NO;
picpicker.navigationBarHidden = NO;
picpicker.wantsFullScreenLayout = NO;
return picpicker;
}
and in:
-(void)viewWillAppear:(BOOL)animated{
if(!self.picpicker){
self.picpicker = [self loadImagePicker];
[self.view addSubview: self.picpicker];
}
}
-(void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.picpicker removeFromSuperview];
self.picpicker = nil;
}

How to set a view to a tag set in code not in Interface Builder?

I have an app that uses 4 different xibs, lets call them 1-4
So you start on view 1, if you press the button it takes you to view 2, on view 2, you have a back button (which takes you to 1) and forward button that takes you to 3 etc
Anyway, I am removing the next page buttons, and have added a swipe control instead of pressing a button, you can swipe to the next page.
However, I need to know how I can call a tagged view, using the swipe.
At the moment, the UIButton for next page is set in IB as tag 1
This is my swipe code (this is page 1 so only has a swipe left)
- (IBAction)swipeLeftDetected:(UIGestureRecognizer *)sender {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
Page2ViewController *UIViewController =
[[Page2ViewController alloc] initWithNibName:#"Page2ViewController~ipad" bundle:nil];
[self presentModalViewController:UIViewController animated:YES];
}else{
Page2ViewController *UIViewController =
[[Page2ViewController alloc] initWithNibName:#"Page2ViewController" bundle:nil];
[self presentModalViewController:UIViewController animated:YES];
Page2ViewController *VC = [[Page2ViewController alloc] initWithNibName:#"Page2ViewController" bundle:nil];
[self presentModalViewController:VC animated:YES];
[self.view removeGestureRecognizer:[self.view.gestureRecognizers lastObject]];
[VC release];
}
}
Whereabout in that code, can I tell it to swipe to tag 1?
Would appreciate any help :)
Thanks,
Chris
---- Updated FAO Rob;
In the appdelegate.m
- (void)swicthView:(int)viewControllerIndex :(CGRect)viewRect {
if (viewControllerIndex < 0 || viewControllerIndex > viewControllers.count) {
//invalid index passed to function - do nothing
}else{
if (subViewForceUseNibSize == NO) {
//pass the view frame size at runtime
if (CGRectIsEmpty(viewRect) || viewControllerIndex == 0) {
//no frame size so force full screen
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
viewRect =CGRectMake(0, 0, 320, 480);
}else{
viewRect = CGRectMake(0, 0, 768, 1024);
}
}
}else{
//force use the nib size, so reduce size of NIB to leave display of NIB main nib below
viewRect = ((UIViewController *)[viewControllers objectAtIndex:viewControllerIndex]).view.frame;
}
}
//swicth our view
if (viewControllerIndex == 0) {
/*
for (UIView *subview in window.rootViewController.view.subviews) {
[window.rootViewController.view sendSubviewToBack:subview];
}
*/
for (int x = 1; x<[viewControllers count]; x++) {
if (((UIViewController *)[viewControllers objectAtIndex:x]).view.superview != nil) {
[window.rootViewController.view sendSubviewToBack:((UIViewController *)[viewControllers objectAtIndex:x]).view];
}
}
[window bringSubviewToFront:((UIViewController *)[viewControllers objectAtIndex:0]).view];
return;
}
if (((UIViewController *)[viewControllers objectAtIndex:viewControllerIndex]).view.superview != nil) {
((UIViewController *)[viewControllers objectAtIndex:viewControllerIndex]).view.frame = viewRect;
[window.rootViewController.view bringSubviewToFront:((UIViewController *)[viewControllers objectAtIndex:0]).view];
[window.rootViewController.view bringSubviewToFront:((UIViewController *)[viewControllers objectAtIndex:viewControllerIndex]).view];
}else{
((UIViewController *)[viewControllers objectAtIndex:viewControllerIndex]).view.frame = viewRect;
[window.rootViewController.view bringSubviewToFront:((UIViewController *)[viewControllers objectAtIndex:0]).view];
[window.rootViewController.view addSubview:((UIViewController *)[viewControllers objectAtIndex:viewControllerIndex]).view];
}
}
Looking at the revised code sample, it is clear that there is a UIAppDelegate method called swicthView [sic] that is used for transitioning between five different view controllers, all of which are loaded simultaneously. Given this structure, it is advised that you have a property to keep track of which of the five pages is loaded, and based on the left or right swipe, invoke swicthView to transition to that controller. Thus:
#interface ViewController ()
#property (nonatomic) NSInteger currentPage;
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.currentPage = 0;
UISwipeGestureRecognizer *gesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleLeftSwipe:)];
gesture.direction = UISwipeGestureRecognizerDirectionLeft;
[self.view addGestureRecognizer:gesture];
[gesture release];
gesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleRightSwipe:)];
gesture.direction = UISwipeGestureRecognizerDirectionRight;
[self.view addGestureRecognizer:gesture];
[gesture release];
// the rest of the viewDidLoad
}
- (void)handleLeftSwipe:(UISwipeGestureRecognizer *)gesture {
if (self.currentPage < 4)
{
++self.currentPage;
[UIAppDelegate swicthView:self.currentPage :CGRectZero];
}
}
- (void)handleRightSwipe:(UISwipeGestureRecognizer *)gesture {
if (self.currentPage > 0)
{
--self.currentPage;
[UIAppDelegate swicthView:self.currentPage :CGRectZero];
}
}
Frankly, I'd strong advise retiring the swicthView design and rather employing a custom container view controller. If you watch WWDC 2011 - Implementing a UIViewController containment, you'll see a good introduction about the importance of keeping a view controller hierarchy synchronized with a view hierarchy, and see some practical demonstrations of custom containers.
The original answer, provided below, was based upon the original snippet of code that was performing presentViewController. It turns out that a very different solution was called for, outlined above, but I retain the original answer for historical purposes:
Original answer:
I assume you have the following sort of code in viewDidLoad:
UISwipeGestureRecognizer *gesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleLeftSwipe:)];
gesture.direction = UISwipeGestureRecognizerDirectionLeft;
[self.view addGestureRecognizer:gesture];
And then you gesture handler could be:
- (void)handleLeftSwipe:(UISwipeGestureRecognizer *)gesture
{
NSString *nibName;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
nibName = #"Page2ViewController~ipad";
else
nibName = #"Page2ViewController";
Page2ViewController *controller = [[Page2ViewController alloc] initWithNibName:nibName bundle:nil];
// if supporting iOS versions earlier than 5.0, then you should use:
//
// [self presentModalViewController:controller animated:YES];
//
// otherwise you should use presentViewController as done below.
[self presentViewController:controller animated:YES completion:nil];
[controller release];
}
Note, I'm don't remove the gesture (unless you really don't want the gesture there when you return back to this view, which is unlikely). Also note, I'm creating controller, presenting, and releasing.
I'm not understanding your repeated reference to tag properties in this context, as numeric tag values are used for identifying subviews of a view, not for identifying view controller or anything like that. So you say "UIButton for next page is set in IB as tag 1" and later you ask "Whereabout ... can I tell it to swipe to tag 1?" It doesn't make sense to "swipe to a button". You could, though, have the two handlers, the button's IBAction (which I'll call onPressNextButton ... I don't know what you called it) and the handleLeftSwipe call the same method, e.g.:
- (void)handleLeftSwipe:(UISwipeGestureRecognizer *)gesture
{
[self goToNextViewController];
}
- (IBAction)onPressNextButton:(id)sender
{
[self goToNextViewController];
}
- (void)goToNextViewController
{
NSString *nibName;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
nibName = #"Page2ViewController~ipad";
else
nibName = #"Page2ViewController";
Page2ViewController *controller = [[Page2ViewController alloc] initWithNibName:nibName bundle:nil];
[self presentViewController:controller animated:YES completion:nil];
[controller release];
}
References:
presentViewController, the preferred method for modal transitions.
presentModalViewController, the now deprecated method that you use if you need backward compatibility for iOS versions prior to 5.0.
Naming basics in the Coding Guidelines for Cocoa, for advice in naming variables and methods. Note variables generally start with lowercase letters and classes generally start with uppercase letters.

take picture method on cameraOverlayView

My problem;
Hide the default camera controls and overlay it with my my own. This is made with the property cameraOverlayView. I also was having problem triggering the takePicture method.
(Question solved in the comments and in the edits. See Question with no answers, but issue solved in the comments (or extended in chat) )
The OP wrote:
Here is what came to be the solution:
I have two UIViewController. The main ViewController and the CustomOverlay (for the camera controls).
I the ViewController I declare the source type and the overlay for may camera control like this:
- (void)viewDidLoad
{
// notification from the CustomOverlay Controller that triggers the eTakePicture method
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(eTakePicture:) name:#"eTakePicture" object:nil];
daysBtn.delegate = self;
daysBtn.hidden = YES;
picker = [[UIImagePickerController alloc] init];
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
picker.cameraDevice = UIImagePickerControllerCameraDeviceFront;
picker.showsCameraControls = NO;
picker.navigationBarHidden = YES;
picker.wantsFullScreenLayout = YES;
picker.delegate = self;
overlay = [[CustomOverlay alloc] initWithNibName:#"CustomOverlay" bundle:nil];
// Overlay for the camera controls, note the "= overlay.view", the ".view" was important
// because the overlay is a new UIViewcontroller (with xib) so you have to call the
// view. Most tutorials that I saw were based on UIView so only "= overlay" worked.
picker.cameraOverlayView = overlay.view;
[self presentModalViewController:picker animated:NO];
[super viewDidLoad];
}
Now on the CustomOverlay, which is a UIViewController I have the take picture button and want this button to trigger a method in the main ViewController:
- (IBAction)shoot:(id)control {
[[NSNotificationCenter defaultCenter] postNotificationName:#"eTakePicture" object:self];
}
And back to the main ViewController:
-(void)eTakePicture:(NSNotification *)notification
{
[picker takePicture];
}
All the code above will change a little more once I review it, specially the first block where I have to have a condition to check if cameraSourceType is available.
Hope that helps somebody out there. Any question, just ask.

UINavigationController and pushing an openGL UIView = never ending loops

I am trying to push an opengl UIView to my navigation controller like this
GraphViewController *gvc = [[GraphViewController alloc] initWithTicker:[listOfItems objectAtIndex:indexPath.row]];
[self.navigationController pushViewController:gvc animated:YES];
[gvc release];
The initWithTicker method looks like this
-(id) initWithTicker:(NSString*)ticker{
self = [super initWithNibName:nil bundle:nil];
if (self) {
self.title = ticker;
EAGLView *eagl = [[EAGLView alloc] initWithFrame:[UIScreen mainScreen].bounds];
eagl.animationInterval = 1.0 / 60.0;
[eagl startAnimation];
self.view = eagl;
}
return self;
}
When I go back and forward in my UINavigationController, the drawView method (in EAGLView) keeps looping. Furthermore, if I pushViewController again, the first one does not stop and a new one is created! I've tried making this an instance variable so only one is created and it has the same effect. I would be grateful if anyone has insight as to why this is happening
sergio Suggestion:
-(id) initWithTicker:(NSString*)ticker{
self = [super initWithNibName:nil bundle:nil];
if (self) {
self.title = ticker;
}
return self;
}
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
eagl = [[EAGLView alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.view = eagl;
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
eagl.animationInterval = 1.0 / 60.0;
[eagl startAnimation];
[super viewDidLoad];
}
same behaviour.
---This is how I fixed my drawView looping problem--
-(void)viewDidAppear:(BOOL)animated {
[eagl startAnimation];
[super viewDidAppear:animated];
}
-(void)viewDidDisappear:(BOOL)animated {
[eagl stopAnimation];
[super viewDidDisappear:animated];
}
--Craigs solution --
if(graphView == nil){
graphView = [[GraphViewController alloc] initWithTicker:[listOfItems objectAtIndex:indexPath.row]];
}else{
[graphView release];
graphView = [[GraphViewController alloc] initWithTicker:[listOfItems objectAtIndex:indexPath.row]];
}
Are you creating a new GraphViewController every time you want to push one onto your navigation stack? If so, it doesn't really matter how you're handling the creation of your EAGLView instance variable, since you're never going to be interacting with that view controller again anyway.
For example:
User taps something, a new GraphViewController is pushed on the stack
User goes back, this view controller continues to run
Return to 1. and repeat (thus creating a SECOND GraphViewController, and then a third, and then a fourth... etc.)
What you should probably be doing is maintaining your GraphViewController as an instance variable, and only creating it once. This will ensure that you're in turn only creating one EAGLView.
if (_graphViewController == nil) {
_graphViewController = [[GraphViewController alloc] initWithTicker:[listOfItems objectAtIndex:indexPath.row]];
}
[self.navigationController pushViewController:_graphViewController animated:YES];
Then, be sure to release the view controller in your dealloc method if you're going to be maintaining it as an ivar.
Would you try executing this code of yours:
EAGLView *eagl = [[EAGLView alloc] initWithFrame:[UIScreen mainScreen].bounds];
eagl.animationInterval = 1.0 / 60.0;
[eagl startAnimation];
self.view = eagl;
inside of loadView? I am not sure about why your view is behaving like you say, but that is the place where you are supposed to build your UI... so it might make a difference...
Furthermore, I would call [eagl startAnimation]; only in viewDidLoad...
Hope it helps...

Problem with the scrollbar of a UIWebView

Im using a UIWebView to access a website, when i rotate the phone (landscape) the UIWebView is properly resized and the scrollbar are on the right place (on the right edge...) but when i acess any of input fields to fill the information required and exit it the UIWebView scrollbar jumps to the middle of screen (looks like it get back to 320, the width of the screen on portrait). Some useful info, this program was created using IB, have lots of outlets, im thinking about in do (redo) everything programmatically cause i was not the author of the first version... If anyone have seen this before plz let me know..
Thanks in advance!
Dont add your webview into self.view just assign it.Simple thing works like awesome
wv = [[UIWebView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
[self.view addSubview:wv];
instead do
self.view = wv;
In my test case I found that I can replicate this problem by going to a web site that accepts input, invoking the keyboard, dismissing the keyboard (with or without entering any input) and now the vertical scroll bar's display is in the Portrait position.
I tested with and without a NIB and the results are consistent. Once the keyboard is invoked, the vertical scroll bar will remain at the Portrait coordinates when the phone (or simulator) is in Landscape mode.
I submitted case# 7428286.
I received a response from Apple about the possible bug reported, they asked for a sample code that can reproduce the problem, i sent to them and im posting it here so you can test too:
//
// viewController.m
// TesteWebview
//
// Created by GecanMobile01 on 13/11/09.
// Copyright xxx All rights reserved.
//
#import "viewController.h"
#implementation viewController
#synthesize vw, wv;
/*
// The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
// Custom initialization
}
return self;
}
*/
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
vw = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
[vw setBackgroundColor:[UIColor grayColor]];
vw.autoresizesSubviews = YES;
self.view = vw;
wv = [[UIWebView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
[self.view addSubview:wv];
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
NSURL *urlId = [NSURL URLWithString:#"https://www.google.com"];
NSURLRequest *theRequest = [NSURLRequest requestWithURL:urlId cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:(NSTimeInterval)10.0];
[wv loadRequest:theRequest];
[super viewDidLoad];
}
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
CGRect cgrWebView;
BOOL bChangeOrientation = NO;
if (interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight){
if (interfaceOrientation == UIInterfaceOrientationPortrait) {
cgrWebView = CGRectMake(0.0, 0.0, 320.0, 460.0);
bChangeOrientation = YES;
} else {
cgrWebView = CGRectMake(0.0, 0.0, 480.0, 320.0);
bChangeOrientation = YES;
}
[wv setFrame:cgrWebView];
}
return bChangeOrientation;
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
#end
I reported a Bug on begreport.apple.com about this issue.
And today (04/21/2010) got an answer!
"Hello Paulo,
This is a follow-up to Bug ID# 7392537. Engineering believes this issue has been addressed in iPhone OS 4.0 beta seed 2. (8A248c)
After installing the iPhone OS 4.0b2 software, please update this bug report with your results.
Thank you for your time. We truly appreciate your assistance in helping us discover and isolate bugs.
Best Regards,
Patrick Collins
Apple Developer Connection
Worldwide Developer Relations"
I was facing the same problem but I set the frame of web view in
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
{
BOOL orientation = NO;
if(interfaceOrientation == UIInterfaceOrientationPortrait)
{
[webView setFrame:CGRectMake(0, 0, 320, 480)];
orientation = YES;
return orientation;
}else if(interfaceOrientation == UIInterfaceOrientationLandscapeRight)
{
[webView setFrame:CGRectMake(0, 0, 480, 320)];
orientation = YES;
return orientation;
}else {
orientation = NO;
return orientation;
}
}