Set Delegate methods on child view controll - iphone

I am building an application which should allow the user to scroll through the images. Since I have many images (downloaded from the web), what i doing is I have UP and down button on the parent view, in addition i have the scroll view. Based on the selected option (up or down), I add the ImageClass ( created a class which extends UIViewController) view to the scroll view.
Now, on the selected view the user can mark a point or do any stuff.
The question is how from the parent view I can call methods of the Uiviewcontroller. I know how I can set the delegate methods but what I want is that parent controller can call any a method say redraw method which would redraw the entire view.
Code:
-(IBAction) down:(id) sender{
[scrollView2 removeFromSuperview];
}
-(IBAction) down :(id) sender {
[scrollView2 removeFromSuperview];
if(scrollView2 == nil)
scrollView2 = [[UIScrollView alloc] init];
[self.view addSubview:scrollView2];
[self.view sendSubviewToBack:scrollView2];
[scrollView2 setBackgroundColor:[UIColor blackColor]];
[scrollView2 setCanCancelContentTouches:NO];
scrollView2.clipsToBounds = YES;
// default is NO, we want to restrict drawing within our scrollview
scrollView2.indicatorStyle = UIScrollViewIndicatorStyleWhite;
// CSImageView is a class which of the type UIViewController
imageVie = [[CSImageView alloc] init];
[scrollView2 addSubview:imageVie.view];
[scrollView2 setContentSize:CGSizeMake(1500,1500)];
[scrollView2 setScrollEnabled:YES];
[imageView release];
}
Now, from the parent view controller I want to call say:
imageVie.redraw(); method
Code for CSImageView
#interface CSImageView : UIViewController {
NSNumber *imageId ;
}
#property (nonatomic, retain) NSNumber *venueId;
-(void) redraw;
#end
#implementation CSImageView
#synthesize imageId;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)dealloc
{
[super dealloc];
}
- (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.
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
-(void) redraw {
NSLog(#"I am ehre in the test function");
}
#end
Can you please help me on the same. I am not able to call the redraw method. Any input would be appreciated.

First, CSImageView should probably be a subclass of UIView, not UIViewController. You should keep a reference to your instance (i.e. as an instance variable or synthesized property) so you can access it from methods other than - down:.

Wow.
I can't say I follow what you've coded, but here's how you do it.
During this part...add a tag to the view
// CSImageView is a class type UIViewController
imageVie = [[CSImageView alloc] init];
imageVie.tag = 99 // Any number. Preferably a constant
[scrollView2 addSubview:imageVie.view];
...
Then on the parent
view controller. You can ...
-(IBAction) down:(id) sender {
CSImageView *view = [scrollView2 viewWithTag:99];
[view redraw];
... }
Something like that.

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;
}

Unwanted double navigation bar

I made the navigation bar (top bar) appear/disappear when I tap the screen, and also lay on top of the background image. It worked, but with one problem: I've suddenly got two navigation bars! First, one with a back button named "Back", and when I press "Back" it pops up a new navigation bar with a back button named "Vinene", which is the title of the TableView it leads back to. Thats the one I want to keep. I think the issue is somewhere in the DetailViewController.m or in the didselectrowatindexpath in the MasterViewController.m. Hope someone can see the problem!
DetailViewController.m:
#interface WinesDetailViewController ()
#end
#implementation WinesDetailViewController
#synthesize wineDictionary;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.navigationController.navigationBar.translucent = YES;
self.wantsFullScreenLayout = YES;
UITapGestureRecognizer *tap = [[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(hideShowNavigation)] autorelease];
tap.numberOfTapsRequired = 1;
[self.view addGestureRecognizer:tap];
}
- (void) hideShowNavigation
{
[self.navigationController setNavigationBarHidden:!self.navigationController.navigationBarHidden];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (BOOL)hidesBottomBarWhenPushed{
return TRUE;
}
#end
MasterViewController.m:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSDictionary *dictionary = [wine libraryItemAtIndex:indexPath.row];
if (winesDetailViewController == nil) {
// Init the wine detail view
winesDetailViewController = [[WinesDetailViewController alloc] init];
}
// Here you pass the dictionary
winesDetailViewController.wineDictionary = dictionary;
[self.navigationController pushViewController:winesDetailViewController animated:YES];
}
}
Usually, a recurring navigation bar like you describe is caused by something like pushing the same view controller twice. Can you check to ensure you're only pushing a single view controller on to your navigation stack (via breakpoints or logging?). Is it possible that winesDetailViewController is already on the navigation stack? You can also try logging the value of self.navigationController.viewControllers for a hint.
I would also suggest moving
self.navigationController.navigationBar.translucent = YES;
to viewWillAppear and
self.wantsFullScreenLayout = YES;
to your initializer (though I don't think this will solve your problem).

Keeping UIButton highlighted

Hey!
I have a xib file were i would like a round rect button to stay highlighted after it is pressed. I also would like to have a different button that is pressed after the first one that takes you to the next page. How can I do this. Some code would be greatly appreciated!
This is my .h:
#import <UIKit/UIKit.h>
#interface Test1ViewController : UIViewController {
IBOutlet UIButton *button1;
IBOutlet UIButton *button2;
}
-(IBAction) buttonPressed:(id)sender;
-(IBAction) secondButtonPressed:(id)sender;
- (void)flipButton;
#end
This is my .m:
#import "Test1ViewController.h"
#import "Page2.h"
#implementation Test1ViewController
-(IBAction)buttonPressed:(id)sender
{
[self performSelector:#selector(flipButton) withObject:nil afterDelay:0.0];
}
- (IBAction)secondButtonPressed {
if ( button1.selected ) {
Page2 *page2 = [[Page2 alloc] initWithNibName:#"Page2" bundle:nil];
page2.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:page2 animated:YES];
[page2 release];
}
}
/*
// The designated initializer. Override to perform setup that is required before the view is loaded.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
*/
/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/
/*
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
}
*/
/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/
- (void)flipButton {
if ( button1.selected ) {
button1.highlighted = NO;
button1.selected = NO;
} else {
button2.highlighted = YES;
button2.selected = YES;
}
}
- (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
Thanks a lot for all the help!
You will have to use the highlighted property of the button to set the state as highlighted or otherwise. However doing immediately on Touch Up Inside seems to reset it. So we delay the change until the next run loop starts. Do this on the method called on touch.
-(IBAction)buttonPressed:(id)sender
{
[self performSelector:#selector(flipButton) withObject:nil afterDelay:0.0];
}
and define the flip method as follows –
- (void)flipButton {
if ( self.button.selected ) {
self.button.highlighted = NO;
self.button.selected = NO;
} else {
self.button.highlighted = YES;
self.button.selected = YES;
}
}
You can later check on the method called on tap of the other button whether self.button.selected is YES or not and then act on it.
- (IBAction)secondButtonPressed {
if ( self.button.selected ) {
// Load next page.
}
}
Better Approach
Use a UISwitch. Don't you think that it is a natural fit.

insertSubview: AtIndex: does not work

I went through the material regarding this issue but still can't figure it out completely.
The main issue is that i am using this method but the view does not show...
The app is built out of two view - the main one (i added it as a subview to the main nib) -
Has of a text field where i write some text.
Has a button that when pressed, the action method loads a second view that has a label with some text in it.
the source code of the first viewController:
#import <UIKit/UIKit.h>
#class TxtRunnerViewController;
#interface Itai_s_text_app_take_2ViewController : UIViewController {
int sliderSpeed;
IBOutlet UITextField *textInput;
TxtRunnerViewController *trvc;
}
#property (nonatomic, retain) IBOutlet UITextField *textInput;
#property (retain, nonatomic) TxtRunnerViewController *trvc;
- (IBAction)sliderChanged:(id)sender;//speed of text show changed
- (IBAction)textFieldDoneEditing:(id)sender;//dor 'DONE' on keyboard
- (IBAction)backgroundTap:(id)sender;//for handling tapping on background
- (IBAction)textEmButtonPressed:(id)sender;
#end
the .m of the first ViewController:
#import "Itai_s_text_app_take_2ViewController.h"
#import "TxtRunnerViewController.h"
#implementation Itai_s_text_app_take_2ViewController
#synthesize textInput;
#synthesize trvc;
- (IBAction)sliderChanged:(id)sender
{
UISlider *slider = (UISlider *)sender;
sliderSpeed = (int)(slider.value + 0.5f);//setting the speed determinned by the usr in slider
NSLog(#"Slider value is %#", sliderSpeed);
}
- (IBAction)textFieldDoneEditing:(id)sender
{
[sender resignFirstResponder];
NSLog(#"our text input is %#", textInput.text);
}
- (IBAction)backgroundTap:(id)sender
{
[textInput resignFirstResponder];
}
- (IBAction)textEmButtonPressed:(id)sender
{
NSLog(#"button pressed");
if ([textInput.text length]==0)
{
NSString *msg = nil;
msg = #"Write text to transmit";
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Forgot something?"
message:msg
delegate:self
cancelButtonTitle:#"Back"
otherButtonTitles:nil];
[alert show];
[alert release];
[msg release];
}
else { //init
NSLog(#"HI!");
if (self.trvc == nil)
{
NSLog(#"if accepted");
TxtRunnerViewController *tr = [[TxtRunnerViewController alloc] initWithNibName:#"TxtRunner"
bundle:nil];
self.trvc = tr;
[tr release];
}
[self.view removeFromSuperview];
[self.view insertSubview:trvc.view atIndex:0];
NSLog(#"InsertAtIndex was operated...!");
//[self.view addSubview:tvc.view];
}
}
/*
// The designated initializer. Override to perform setup that is required before the view is loaded.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
*/
/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/
/*
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
}
*/
/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/
- (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.
if(self.trvc.view.superview == nil)
self.trvc = nil;
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[trvc release];
[super dealloc];
}
The second View is simply empty (has a label added to it in it's nib file):
#import
#interface TxtRunnerViewController : UIViewController {
}
#end
It's .m file is the default one, added no code to it.
When i press the button in the first view - it's view disappears but the second view does not appear instead, only a blank white view appears, nothing on it.
Doe
If you push the TxtRunnerViewController it will completely hide the first one, but it still exist in background. (without removeFromSuperview)
TxtRunnerViewController *vw = [[TxtRunnerViewController alloc]initWithNibName:#"TxtRunner" bundle:nil];
[self.view pushViewController:vw.view animated:NO];
[vw release];
To remove the first view it's a bit more difficult. You would need to implement a delegate in RootViewController which will be fired after clicking the done Button of the first view. Then in your RootViewController some code is executed which displays the second view and removes the first view.
For a delegate sample open the Utility Application Sample when creating a new project and figure out how it works or search some examples online.
The line:
[self.view removeFromSuperview];
Removes the view from its super
then the call
[self.view insertSubview:trvc.view atIndex:0];
Adds trvc to it - but that view has been removed and not visible anymore.
You need to add trvc to the superview.

Volume control in iPhone OS from another view controller?

If I am playing a sound in one view, does anyone know if it is possible to control the volume from another, if it is can someone explain how? I can't figure it out, I have no code to show for the volume.
The sound is called from one view and the volume slider is on another. I have coded both.
The code for the sound is
#import `<AVFoundation/AVAudioPlayer.h`>
#import "LeftViewController.h"
#implementation LeftViewController
- (IBAction)buttonrm:(id)sender
{
[self dismissModalViewControllerAnimated:YES];
}
- (IBAction)playl {
[theAudio play];
}
- (IBAction)pausel {
[theAudio pause];
}
/*
// 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 viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
NSString *path =[[NSBundle mainBundle] pathForResource:#"The Noisettes - Never Forget You" ofType:#"mp3"];
theAudio = [[AVAudioPlayer alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path] error:NULL];
theAudio.delegate = self;
//[theAudio play];
[super viewDidLoad];
}
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
- (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
the code for the slider is
- (void)viewDidLoad {
[super viewDidLoad];
CGRect sliderRect = CGRectMake(46,124,169,0);
UISlider *VolumeL = [[UISlider alloc] initWithFrame:sliderRect];
VolumeL.minimumValue = 0;
VolumeL.maximumValue = 100;
VolumeL.continuous = YES;
UIImage *sliderctrl = [UIImage imageNamed:#"VolumeL.png"];
//UIImage *stetchLeftTrack = [[UIImage imageNamed:#"volumel12.png"]
//stretchableImageWithLeftCapWidth:5.0 topCapHeight:0.0];
[VolumeL setThumbImage:sliderctrl forState:UIControlStateNormal];
//[VolumeL setMinimumTrackImage:stetchLeftTrack forState:UIControlStateNormal];
[VolumeL addTarget:self action:#selector(sliderAction:) forControlEvents:UIControlEventValueChanged];
VolumeL.transform = CGAffineTransformRotate(VolumeL.transform, 270.0/180*M_PI);
[self.view addSubview:VolumeL];
[VolumeL release];
}
Use the delegate pattern
In the second view controller create a protocol called MyProtocol for example with one method:
- (void)didUpdateVolume:(NSUInteger)volume;
Also create a delegate instance variable to hold the delegate reference
#property (nonatomic, assign) id<MyProtocol> delegate;
And don't forget to synthesize it in the implementation.
When the volume value is updated you would send the value to the delegate
[self.delegate didUpdateVolume:newValue];
Back in the first controller adopt the MyProtocol protocol, implement didUpdateVolume, and set the value in your player.
Try using the Notification center.
http://blog.grio.com/2009/04/broadcasting-information-how-to-use-the-iphone-notification-center.html