How to invoke loadNibNamed without losing UISwipeGestures? - iphone

I'm loading a different xib when the user flips to landscape and that's working great, but I've noticed that my swipe events aren't registered.
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
if ([self currentlyInLandscapeMode:toInterfaceOrientation]) {
[[NSBundle mainBundle] loadNibNamed:#"PhotosLandscape" owner:self options:nil];
}else{
[[NSBundle mainBundle] loadNibNamed:#"PhotosPortrait" owner:self options:nil];
}
}
- (BOOL)currentlyInLandscapeMode:(UIInterfaceOrientation)interfaceOrientation
{
return (UIInterfaceOrientationIsLandscape(interfaceOrientation));
}
How can you switch xib's and keep all the state from my previous view/xib?
UPDATE
turns out my IBOutlets still work but my swipe isn't registered

You can't use a nib file to lay out existing objects. A nib file is stored as an archived object graph, so when you load a nib, either with NSBundle's loadNibNamed: or UIViewController's initWithNibName:, a fresh set of objects gets instantiated.
The only way around this would be to use loadNibNamed to instantiate a new set of objects, and use their frame properties to set the frames for your existing objects, which isn't a great solution.

Turns out I just needed to re-register the swipe event after each nib is loaded (like so)
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
if ([self currentlyInLandscapeMode:toInterfaceOrientation]) {
[[NSBundle mainBundle] loadNibNamed:#"VotePhotosLandscape" owner:self options:nil];
}else{
[[NSBundle mainBundle] loadNibNamed:#"VotePhotosViewController" owner:self options:nil];
}
[self wireupSwipeEvents];
}
- (BOOL)currentlyInLandscapeMode:(UIInterfaceOrientation)interfaceOrientation
{
return (UIInterfaceOrientationIsLandscape(interfaceOrientation));
}
- (void)wireupSwipeEvents
{
UISwipeGestureRecognizer *recognizer;
recognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(handleSwipeFrom:)];
[recognizer setDirection:UISwipeGestureRecognizerDirectionLeft];
[[self view] addGestureRecognizer:recognizer];
[recognizer release];
}

Related

Navigation Bar missing in iphone

I am very new to iPhone development, but I have been given an iPhone application to debug and I don't know where to start.
The problem is as follows:
The app has a view which has a navigation bar on top. When I press the home button on the device, the application goes to suspended mode I suppose. When I go back to the app from the list I can see the view but without navigation bar. Why would the navigation bar disappear, and how can I fix it?
Here is the code for the same
-(void)viewWillAppear:(BOOL)animated
{
[self prepareNavBar];
}
-(void)prepareNavBar
{
self.navigationItem.hidesBackButton = NO;
CustomNavBar *the_pNavBar = [[CustomNavBar alloc] init];
[the_pNavBar prepareNavbarWithLeftButtonImage:nil leftButtonAction:nil titleImage: [UIImage imageWithContentsOfFile:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"ip4_heading_comments.png"]] rightButtonImage:[UIImage imageWithContentsOfFile:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"ip4_submit.png"]] rightAction:#selector(postComment) target:self backgroundImage:[UIImage imageWithContentsOfFile:[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"ip4_background_grey_150px.png"]] navigationBar:self.navigationController.navigationBar isStandardNavBar:NO];
[the_pNavBar release];
}
please let me know if any other code is required
I fixed the issue by the following code
-(void)didBecomeActive:(NSNotificationCenter *)in_pNotif
{
[self performSelector:#selector(test) withObject:nil afterDelay:0.01];
}
-(void)test
{
self.navigationController.toolbarHidden = YES;
}

Change nib programmatically when orientation changes

I load my nibs like this in the init:
self = [super initWithNibName:#"PageView_iPhone" bundle:nil];
But how do I change this during runtime (i.e. after the init) if the orientation changes? initWithNibName won't work.
If you really want to load a different nib, you could use:
[[NSBundle mainBundle] loadNibNamed:#"PageView_iPhone" owner:self options:nil];
NSArray* nibViews = [[NSBundle mainBundle] loadNibNamed:#"PageView_iPhone"
owner:self
options:nil];
PageView_iPhone* myView = [nibViews objectAtIndex:0];
During init, I setup my views (create them programatically) and create extra CGPoint's for center positions or CGRect's for frames for each view in the view controller.
After the views are created in init, I call method named layoutViewsForOrientation to set the initial position, passing in the current status bar orientation. When the orientation changes, I use this code:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
BOOL result = NO;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
result = (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
} else {
result = YES;
}
if( result == YES ) [self layoutViewsForOrientation:interfaceOrientation];
return result;
}
There may be an easier way, but this works well for my needs.

Flipping a Video Horizontally in Xcode

I have a video such that when I play it in full view and flip the simulator horizontally the video would not flip. How can I make the video flip according to the iPhone's accelerometer?
Here is the code for the video if it helps:
- (void)viewDidAppear:(BOOL)animated {
NSBundle *bundle=[NSBundle mainBundle];
NSString *moviePath = [bundle pathForResource:#"MainPageMovie" ofType:#"mp4"];
NSURL *movieURL=[[NSURL fileURLWithPath:moviePath] retain];
MPMoviePlayerController *theMovie = [[MPMoviePlayerController alloc] initWithContentURL:movieURL];
theMovie.scalingMode = MPMovieScalingModeAspectFill;
theMovie.view.frame = CGRectMake(115.0, 156.0, 200.0, 150.0);
[self.view addSubview:theMovie.view];
[theMovie play];
[super viewDidLoad];
self.view.backgroundColor = [UIColor viewFlipsideBackgroundColor];
}
Your MPMoviePlayerController view is added as a subview to another view controller's view. In that parent view controller, have you overridden shouldAutorotateToInterfaceOrientation method?
If you are just looking for landscape (horizontal) rotation, you can have your code as below:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Overriden to allow any orientation.
return ((interfaceOrientation == UIInterfaceOrientationLandscapeLeft) || (interfaceOrientation == UIInterfaceOrientationLandscapeRight));
}
In order to rotate specific subviews of the larger view controller view, (which in your situation would be the case with only rotating the video), you'd have to do CGAffineTransforms. This would allow you to resize a view, rotate it, etc. AFAIK, this is probably the best route to go for rotating a single view.
However, you may want to research more into MPMoviePlayerViewController. Take a look at this post, it seems to address your problem.

How to change a new nib when I rotate the device?

I have a helloController which is a UIViewController, if I rotate the device, I want it change it to load a new nib "helloHorizontal.xib", how can I do? thank you.
You could you something like this, (I dont have xcode handy so this code might not be completely accurate)
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if((interfaceOrientation == UIInterfaceOrientationLandscapeRight) || (interfaceOrientation == UIInterfaceOrientationLandscapeLeft)){
WhatYourNewViewClassISCAlled* newView = [[WhatYourNewViewClassISCAlled alloc] initWithNibName:#"NIBNAME" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:newView animated:YES];
}
This is the correct way, I believe. I'm using it in my apps and it works perfectly
triggers on WILL rotate, not SHOULD rotate (waits until the rotate anim is about to start)
uses the Apple naming convention for landscape/portrait files (Default.png is Default-landscape.png if you want Apple to auto-load a landscape version)
reloads the new NIB
which resets the self.view - this will AUTOMATICALLY update the display
and then it calls viewDidLoad (Apple will NOT call this for you, if you manually reload a NIB)
(NB stackoverflow.com requires this sentence here - there's a bug in the code formatter)
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
if( UIInterfaceOrientationIsLandscape(toInterfaceOrientation) )
{
[[NSBundle mainBundle] loadNibNamed:[NSString stringWithFormat:#"%#-landscape", NSStringFromClass([self class])] owner:self options:nil];
[self viewDidLoad];
}
else
{
[[NSBundle mainBundle] loadNibNamed:[NSString stringWithFormat:#"%#", NSStringFromClass([self class])] owner:self options:nil];
[self viewDidLoad];
}
}

UITextField stopping shake event?

For those of you who work graphically, here is a diagram of the view hierarchy:
Root View -> UINavigationController -> UITableView -> Edit View -> Problem UITextfield
Basically, - (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event; gets called in my Root View when the device shakes.
When a user taps on the "edit" icon (a pen, in the bottom of the screen - not the traditional UINavigationBar edit button), the main view adds a subview to itself and animates it on to the screen using a custom animation.
This subview contains a UINavigationController which holds a UITableView. The UITableView, when a cell is tapped on, loads a subview into itself. This second subview is the culprit. For some reason, a UITextField in this second subview is causing problems.
When a user taps on the view, the main view will not respond to shakes unless the UITextField is active (in editing mode?).
Additional info:
My Motion Event Handler:
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event {
NSLog(#"%#", [event description]);
SystemSoundID SoundID;
NSString *soundFile = [[NSBundle mainBundle] pathForResource:#"shake" ofType:#"aif"];
AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath:soundFile], &SoundID);
AudioServicesPlayAlertSound(SoundID);
[self genRandom:TRUE];
}
The genRandom: Method:
/* Generate random label and apply it */
-(void)genRandom:(BOOL)deviceWasShaken{
if(deviceWasShaken == TRUE){
decisionText.text = [NSString stringWithFormat: (#"%#", [shakeReplies objectAtIndex:(arc4random() % [shakeReplies count])])];
}else{
SystemSoundID SoundID;
NSString *soundFile = [[NSBundle mainBundle] pathForResource:#"string" ofType:#"aif"];
AudioServicesCreateSystemSoundID((CFURLRef)[NSURL fileURLWithPath:soundFile], &SoundID);
AudioServicesPlayAlertSound(SoundID);
decisionText.text = [NSString stringWithFormat: (#"%#", [pokeReplies objectAtIndex:(arc4random() % [pokeReplies count])])];
}
}
shakeReplies and pokeReplies are both NSArrays of strings. One is used for when a certain part of the screen is poked and one is for when the device is shaken. The app will randomly choose a string from the NSArray and display onscreen.
As always, code samples are appreciated. I've added my own to help explain the problem.
try using [self.view endEditing:YES];
and for key board to be glassy use:
[textfield setKeyboardAppearance:UIKeyboardAppearanceAlert];
Hope this helps.
Thanks,
Madhup
Keyboard: Look for UIKeyboardAppearanceAlert
As for the shake detection. Once the UITextField resigns first responder (not in focus, keyboard hidden), you need to make sure another UIResponder in the chain becomes firstResponder. For example, if you have a button that sends -resignFirstResponder to the text field, you'll need to do this:
- (IBAction)pressButton {
[textField resignFirstResponder];
[self becomeFirstResponder];
}