Connecting ipad to external monitor - cocoa-touch

I am trying to connect my ipad app to an external screen using the following (not checking the correct resolution for now - just want it up and running).
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[window addSubview:[navigationController view]];
if ([[UIScreen screens] count] > 1) {
window.screen = [[UIScreen screens] objectAtIndex:1];
}
[window makeKeyAndVisible];
return YES;
}
Is this supposed to redirect everything to the external monitor? How dows it work with touches/gestures? I see in the Apple apps, the controls etc are left on the ipad screen...

You need to have a separate UIWindow instance for each screen you are displaying onto (iPad, external monitor, etc.). Rather than simply set your main UIWindow's screen to the external display, you'll want to create a distinct UIWindow for that display and possibly move your views from the iPad window to the external display window. Otherwise, you won't be able to receive touch input on the iPad screen for controlling what's displayed remotely.
For example, the following code will create a new window on an external display (with externalScreen being the appropriate UIScreen instance):
CGRect externalBounds = [externalScreen bounds];
externalWindow = [[UIWindow alloc] initWithFrame:externalBounds];
UIView *backgroundView = [[UIView alloc] initWithFrame:externalBounds];
backgroundView.backgroundColor = [UIColor whiteColor];
[externalWindow addSubview:backgroundView];
[backgroundView release];
externalWindow.screen = externalScreen;
[externalWindow makeKeyAndVisible];
You will also want to watch for screen connection / disconnection events in your application, and deal with them appropriately. To do this, listen for the UIScreenDidConnectNotification and the UIScreenDidDisconnectNotification.
I have a crude example of this working within the latest code of my Molecules iPhone / iPad application, if you want to see one way of handing the external display.

Related

Unable to detect iPhone Retina 4-inch screen size in simulator

I want to make my iOS application support iPhone 5. So I created a separate xib set for iPhone 5 size. Then I load each xib by checking the screen height.
This is the splash screen loading code inside the AppDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
UIViewController *viewController1;
if ([UIScreen mainScreen].bounds.size.height==480) {
viewController1 = [[SplashScreen alloc] initWithNibName:#"SplashScreen" bundle:nil];
}
if ([UIScreen mainScreen].bounds.size.height==568) {
viewController1 = [[SplashScreen alloc] initWithNibName:#"SplashScreen5" bundle:nil];
}
self.window.rootViewController = viewController1;
[self.window makeKeyAndVisible];
return YES;
}
But when I change the simulator into Retina 4-inch, my code doesn't get the emulator size. It always executes the 480 if condition.
But other apps I created like this are working properly.
What is the reason for this?
I'm having the exact same problem right now (at the worst moment, of course....).
It did work properly for several weeks, and for a unknown reason, the simulator suddenly considers the 4in simulated device as a 3.5in screen.
cleaning, reset, reboot : same situation...
EDIT : ok, problem solved. T'was because of a missing Default image in the -568#2x format. I knew that was a condition to make the system work, but xcode had apparently decided to get rid off the one I chose. oh well...

Adding splashscreen to iphone app in AppDelegate

I'm running xcode-4.2 and the project is based for ios5 using storyboards.
I've created a single view application , using the template provided by Apple.
In the storyboard I the removed the viewcontroller created for me and added a UITabBarController.
Next I added a new class MyTabBarController which is a subclass of UITabBarController.
Now I want to show a splashscreen before the TabBar appears. So I can do some loading and calculation in the background.
I thought AppDelegate.m would be a good place for this. Since that's the place where my rootview get's loaded not ? Or should a show the splashscreen from the rootviewcontroller which is MyTabBarController in my case ?
So I created a xib file. I'm surprised you can add .xib files to ios5 storyboard projects. The xib file is called SplashView.xib it has a single view with an image on it.
Code in AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
_splashScreen = [[UIViewController alloc] initWithNibName:#"SplashView" bundle:nil];
//_splashScreen is defined as:#property (strong, nonatomic) UIViewController *splashScreen;
[_window.rootViewController presentModalViewController:_splashScreen animated:NO];
[self performSelector:#selector(hideSplash) withObject:nil afterDelay:2];
return YES;
}
The problem is nothing happens. Even if I change the value from 2 to 200. The application starts up as if there is no splashscreen.
As you might have noticed I'm still struggling with the design of objective-c and iphone application. I hope a decent answer to my question will bring some clarity to the subject.
Thanks in advance!
Splash screens are built into iOS apps. All you need to do is create a file called Default.png and Default#2x.png (for retina displays) and it will work as a splash screen for when the app launches.
You can also set what these images will be in your apps info.plist.
I've dealt with a few clients who wanted to use an animated splash.
Though I'm totally against this, following Apple's HIG,
those clients just don't understand...
Anyway, since - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions; has to return boolean,
it's very important not to halt it for anything.
Also, since launch time is measured by iOS, if it's taking too long, the app will be terminated by iOS!
For this reason, I often use - (void)applicationDidBecomeActive:(UIApplication *)application;
with some kind of flag to indicate if it happened at launch or at returning from background mode.
Or, you should use a NSTimer or - (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay;
so, didFinishLaunchingWithOptions can return without being blocked for processing your animated splash.
This delayed performSelector should be implemented not only for hiding action (like the way you intended it), but also for starting the animation.
If you are using storyboard, you can just add the splash UIImageView to your window.rootViewController.view like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIImage *splashImage = [UIImage autoAdjustImageNamed:#"Default.png"];
UIImageView *splashImageView = [[UIImageView alloc] initWithImage:splashImage];
[self.window.rootViewController.view addSubview:splashImageView];
[self.window.rootViewController.view bringSubviewToFront:splashImageView];
[UIView animateWithDuration:1.5f
delay:2.0f
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
splashImageView.alpha = .0f;
CGFloat x = -60.0f;
CGFloat y = -120.0f;
splashImageView.frame = CGRectMake(x,
y,
splashImageView.frame.size.width-2*x,
splashImageView.frame.size.height-2*y);
} completion:^(BOOL finished){
if (finished) {
[splashImageView removeFromSuperview];
}
}];
return YES;
}
I think the reason why directly just add the UIImageView to window is because iOS will bring the rootViewController.view to front when the default splash will hide. And this will overlap the animation. This means the animation does happen but it's behind the rootViewController.
I just add an identical image to the launch image to my first view controller and then fade it (or whatever animation you require) - this avoids pausing the app load in the AppDelegate.
You need to ensure that the image has the same size and origin as your launch image e.g. to set the image to display on my first view controller which is a tableViewController:
UIImageView *imageView = [[UIImageView alloc] initWithFrame:self.tableView.bounds];
imageView.image = [UIImage imageNamed:#"[imagename]"];
[self.tableView addSubview:imageView];
[self.tableView bringSubviewToFront:imageView];
// Fade the image
[self fadeView:imageView];
-(void)fadeView:(UIView*)viewToFade
{
[UIView animateWithDuration:FADE_DURATION
animations:^ {
viewToFade.alpha = 0.0;
}
];
}

Adding admob to base appdelegate so it can be persistent thoughout all views

I want to add admob to the base app delegate so that I can have a persistent ad that will show though out all views instead of refreshing the every time i change the view Controllers.
"bannerView_.rootViewController = self;" is the problem i do not know how to get this to work across all the view controllers. How can I from the base app delegate be able to get the current viewcontroller displayed on the app.
This is the code that i have currently in app delegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Create a view of the standard size at the bottom of the screen.
bannerView_ = [[GADBannerView alloc]
initWithFrame:CGRectMake(0.0,
self.window.frame.size.height -
GAD_SIZE_320x50.height,
GAD_SIZE_320x50.width,
GAD_SIZE_320x50.height)];
// Specify the ad's "unit identifier." This is your AdMob Publisher ID.
bannerView_.adUnitID = #"a14e0dssddb01d";
// Let the runtime know which UIViewController to restore after taking
// the user wherever the ad goes and add it to the view hierarchy.
bannerView_.rootViewController = self;
// Initiate a generic request to load it with an ad.
[bannerView_ loadRequest:[GADRequest request]];
//[self.window addSubview:navController.view];
[self.window addSubview:bannerView_];
[self.window makeKeyAndVisible];
return YES;
}

How to load a new view upon orientation change - iOS SDK xcode Interface builder

So I am developing this view based app and I have an app that I want to start in landscape mode (haven't quite worked out how to do that, because in the plist file the "initial device orientation" isn't an option as I am assuming it used to be, from what people have said (I'm new to this app developing thing)).
Anyway I want to switch to a completely new view when I rotate to Portrait, and also a another new view when I rotate to portrait upside down. Up to now I have added View2Viewcontroller.(h+m) into my classes and also View2.xib into my resources.
I have this code:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
if((fromInterfaceOrientation == UIInterfaceOrientationLandscapeLeft) ||
(fromInterfaceOrientation == UIInterfaceOrientationLandscapeRight))
{
// Load the view controller I want to display in portrait mode...
}
}
But I'm not too sure how to load the view controller or even where to put this code.
I advise to you use .nibv files, it's better to understand how to initilize view in by code.
anyway there is what you need.
[[viewController alloc] initWithNibName:#"viewController" bundle:[NSBundle mainBundle]];
in code you can do the same without nib filesw by this code
CGRect rect = [[UIScreen mainScreen] bounds];
//create a full-screen window
window = [[UIWindow alloc] initWithFrame:rect];
//create our view controller and add its view to the window
viewController = [ViewController new];
[window addSubview:[viewController view]];
[window makeKeyandVisible];

Multiple MPMoviePlayerViewController fullscreen movie init & switching issue - Fullscreen View doesn't autorotate and minor similar issues

This is my first post at SO. I would like to thank all of the SO users, their contribution have helped me a lot in all of my projects. I am new to the iPhone Application development scene.
Aim of the project is to have a custom interactive User Interface (UI) on top of Movie Player objects (*.mov files on device). The underlying FullScreen MoviePlayers can be more than one and need to switch to different ones based on user Interaction.
I am using cocos2D to achieve the custom interactive UI and effects (for e.g. particle effects on swipe gesture). And I am using Multiple MPMoviePlayerViewController* to play the resident movie files (*.mov) on fullscreen mode (refered to MoviePlayer sample).
Requirement is to switch between movies by switching between default and alternate moviePlayer upon touch detection. Also, the switching should be as smooth as possible.
To achieve smooth switching I am using two moviePlayerViewControllers, each a subview of UIView object in AppController.
Problem a: I am not sure if this is the right way to achieve movie switching.
Problem b: In my current solution. The Default MoviePlayer is rotated in portrait mode, and sometimes the moviePlayer object is not visible. The behaviour is not consistent.
Problem c: The Alternate movie player (object of MPMoviePlayerViewController and added first as subview of UIWindow) rotates on device rotation and behaves properly the Default Movie Player (object of MPMoviePlayerViewController added after) doesn't. Can't think of logical explanation of it. Somewhere I read that MPMoviePlayerViewController creates it's own window and that might be an issue.
// From AppController.h
UIWindow *window; // Parent application window
UIView *viewCocos2D; // Cocos View
UIView *viewMovie; // Default MoviePlayer View
UIView *viewMovieAlternate; // Alternate MoviePlayer View
// From AppController.m
// From DidAppFinishLoading
{
...
// Init the window
window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Init the views (Cocos2d, MOviePlayer and AlternateMOviePlayer)
viewCocos2D = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
viewMovie = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
viewMovieAlternate = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// cocos2d will inherit these values
[viewCocos2D setUserInteractionEnabled:YES];
[viewCocos2D setMultipleTouchEnabled:YES];
// create OpenGL view and attach it to a window
//[[[UIApplication sharedApplication] keyWindow] addSubview:window];
[[CCDirector sharedDirector] attachInView:viewCocos2D];
// Default texture format for PNG/BMP/TIFF/JPEG/GIF images
[CCTexture2D setDefaultAlphaPixelFormat:kCCTexture2DPixelFormat_RGBA8888];
// Create a
customMoviePlayerWithUI = [[CustomMoviePlayerWithUI alloc] initWithSuperView:window andMovieView:viewMovie andAlternateView:viewMovieAlternate andSelf:self];
CCScene *scene = [CCScene node];
CocosCustomLayer *cocosLayer = [customMoviePlayerWithUI cocosLayer];
[window addSubview:viewMovieAlternate];
[window addSubview:viewMovie];
// somehow this order lets cocos2D receive the touch events
[window addSubview:viewCocos2D];
[scene addChild: cocosLayer];
[window makeKeyAndVisible];
[[CCDirector sharedDirector] runWithScene: scene];
[UIAccelerometer sharedAccelerometer].delegate = self;
[customMoviePlayerWithUI start];
[self didRotate:nil];
...
}
So the View hierarchy is
Alternate Movie Player View is at bottom
Default Movie Player view is next
Cocos2D Layer View is on top -- Cocos2D view also receives all of the events.
// From CustomMoviePlayerWithUI.h
MPMoviePlayerViewController *moviePlayerView;
MPMoviePlayerViewController *moviePlayerViewAlternate;
// These delegates are used frequently to invoke some functions
AppController* delegateApplication;
UIView *delegateSuperWindow; // Window which contains everything -
UIView *delegateView; // View containing default MoviePlayer
UIView *delegateViewAlternate;// View containing alternate MoviePlayer
Following is the moviePlayerViewController init code -- basically it allocs and inits two moviePlayerViewController objects and adds them as subview to the Default and Alternate UIView objects from AppController
// From customMoviePlayer.m
// initAndPlayMovie is called from the init of CustomMoviePlayer
- (void)initAndPlayMovie:(UIView *)view andAlternateView:(UIView*) viewMovieAlternate
{
// Initialize a movie player object with the specified URL
moviePlayerView = [[MPMoviePlayerViewController alloc] init];
moviePlayerViewAlternate = [[MPMoviePlayerViewController alloc] init];
[moviePlayerView shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationLandscapeLeft];
[moviePlayerViewAlternate shouldAutorotateToInterfaceOrientation:UIInterfaceOrientationLandscapeLeft];
//if (moviePlayer)
if (moviePlayerView && moviePlayerViewAlternate)
{
[[[moviePlayerView moviePlayer] backgroundView] setBackgroundColor:[UIColor blueColor]];
[[[moviePlayerViewAlternate moviePlayer] backgroundView] setBackgroundColor:[UIColor redColor]];
//[moviePlayerView setWantsFullScreenLayout:YES];
// private API call.. don't use it..
//[mp setOrientation:UIDeviceOrientationPortrait animated:NO];
[view addSubview:[moviePlayerView view]];
[viewMovieAlternate addSubview:[moviePlayerViewAlternate view]];
//[view bringSubviewToFront:[moviePlayerView view]];
//[[moviePlayerView moviePlayer] play];
}
}
Thanks for all of your help. Let me know if you need any more details on it.