UIImagePickerController Freezes when camera flips - objective-c

My UIImagePickerController freezes and the camera closes when the button to flip the camera from front to back is pressed. This is how I initialize the image picker controller object within the project (the rest of the code was ommitted) from the methods as it is irrelevant to the UIimagepickercontroller object.
//In my .h file
UIImagePickerController * imgPicker;
//in my .m file
-(void)viewDidLoad {
imgPicker = [[UIImagePickerController alloc] init];
imgPicker.delegate = self;
imgPicker.allowsEditing = YES;
}
-(void) takePicture {
imgPicker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:imgPicker animated:YES completion:NULL];
}
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
masterImage.image = [info objectForKey:UIImagePickerControllerEditedImage];
if(masterImage.image == nil) {
masterImage.image = [info objectForKey:UIImagePickerControllerEditedImage];
}
[self dismissModalViewControllerAnimated:YES];
}
-(void) imagePickerControllerDidCancel:(UIImagePickerController *)picker{
[self dismissModalViewControllerAnimated:YES];
}
-(void) releaseOutlets {
[imgPicker release];
}

Just for rule, change your code. Instead of:
UIImagePickerController * imgPicker;
Write in your .h file:
#property (nonatomic, strong) UIImagePickerController * imgPicker;
than synthesize it in your .m file:
imgPicker = _imgPicker;
and next every call to this property call with self.

first of all, you should not alloc init in viewdidload method. Do all ur allocations in -init method.
add property as suggested by edzio27.
test again
if problem persists:
- check if u are "receiving memory warning". In case of memory warning ur viewdidload method is called again. In case u keep ur alloc init in that method u will be creating new instance everytime.
We faced a similar issue with MPMoviePlayerController. not sure if u have the same issue.

Related

Changing text of IBOutlet UILabel via delegate

I am trying to change the text of an UILabel that is created via Storyboard. I have two ViewControllers, FirstViewController and SecondViewController. I dismiss the SecondViewController, call the method in the SecondViewController, the delegate method is called in the FirstViewController but the UILabel is nil.
Any idea why?
SecondViewController
-(void)back {
[self.navigationController popToRootViewControllerAnimated:YES];
[self.delegate points:#"10"];
}
FirstViewController
-(void)points:(NSString *)point {
labelPoints.text = [NSString stringWithFormat:#"Points: %#", point];
}
Is your FirstViewController rootViewController? Else pushing to rootViewController will remove First ViewController from stack. From Second View Controller first call delegate and then popViewController as below.
-(void)back {
[self.delegate points:#"10"];
[self.navigationController popViewControllerAnimated:YES];
}
You're popping the VC before you set the value. I would pop from your delegate object like this:
-(void)back {
[self.delegate points:#"10"];
}
-(void)points:(NSString *)point {
labelPoints.text = [NSString stringWithFormat:#"Points: %#", point];
[self.navigationController popToViewController:self animated:YES];
}
If this doesn't solve it, then you likely have another issue besides this one and would have to post more code.
Delay in setting text in UILabel worked for me
For example when delegate calls method like this:
[self.delegate selectedAttendee:dictAttendee];
[self.navigationController popViewControllerAnimated:YES];
This didn't worked for me:
-(void)selectedAttendee:(NSDictionary *)dictAttendee
{
lblMessageTo.text = [dictAttendee objectForKey:#"name"];
}
Solution
-(void)selectedAttendee:(NSDictionary *)dictAttendee
{
[self performSelector:#selector(addTextInMessageTo:) withObject:dictAttendee afterDelay:0.3];
}
-(void)addTextInMessageTo:(NSDictionary *)dictAttendee
{
lblMessageTo.text = [dictAttendee objectForKey:#"name"];
}

UIViewController Retaining in ARC

I have a subclass of UIViewController -> MyPopUpViewController
#protocol MyPopUpViewController Delegate;
#interface MyPopUpViewController : UIViewController
{
}
#property (nonatomic, strong) id <MyPopUpViewControllerDelegate> delegate;
-(IBAction) buttonPressed:(id)sender;
#end
#protocol MyPopUpViewControllerDelegate
-(void) popupButtonPressed: (MyPopUpViewController*)controller;
#end
I cannot have this MyPopUpViewController as an instance variable because this comes externally, and there could be many and multiple of these popups can be up. So far I tried this, and it crashes on the delegate call due to not being retained:
MyMainViewController:
-(void)externalNotificationReceived: (NSString*) sentMessage
{
MyPopUpViewController *popupView = [[MyPopUpViewController alloc] init];
popupView.delegate = self;
[self.view addSubview:popupView.view];
[popupView setInfo :sentMessage :#"View" :#"Okay"];
popupView.view.frame = CGRectMake(0, -568, 320, 568);
popupView.view.center = self.view.center;
}
-(void)popupButtonPressed:(MyPopUpViewController *)controller :(int)sentButtonNumber
{
NSLog(#"Popup Delegate Called");
[controller.view removeFromSuperview];
controller.delegate = nil;
controller = nil;
}
Once the popup comes up, and when the ok button is tapped, it crashes and never gets to that NSLog. How can I change
MyPopUpViewController *popupView = [[MyPopUpViewController alloc] init];
..so it would retain without making it an instance variable?
Thanks in advance.
You should be doing proper view controller containment by calling addChildViewController:.
- (void)externalNotificationReceived: (NSString*) sentMessage {
MyPopUpViewController *popupView = [[MyPopUpViewController alloc] init];
popupView.delegate = self;
[popupView setInfo :sentMessage :#"View" :#"Okay"];
popupView.view.frame = CGRectMake(0, -568, 320, 568);
popupView.view.center = self.view.center;
[self addChildViewController:popupView];
[self.view addSubview:popupView.view];
[popupView didMoveToParentViewController:self];
}
This will keep a proper reference to the view controller as well as properly pass various view controller events. Read about this in the docs for UIViewController and the "View Controller Programming Guide for iOS".
BTW - you should name your methods better. Example:
popupButtonPressed::
should be named:
popupButtonPressed:buttonNumber:
Usually delegates are weak-referenced instead of strong. I, myself, would name it something else as to not confuse other people.
Also, the following bit of code will have no effect:
-(void)popupButtonPressed:(MyPopUpViewController *)controller :(int)sentButtonNumber
{
...
controller = nil;
}
the controller would be released (set to nil) automatically at the end of the scope.

UIGestureRecognizer - Get the reference to the touched UIViewController Instead of its View?

How do I get a reference to the UIViewController of a touched view?
I am using a UIPanGestureRecognizer on the view of a UIViewController. Here's how I initialize it:
TaskUIViewController *thisTaskController = [[TaskUIViewController alloc]init];
[[self view]addSubview:[thisTaskController view]];
UIPanGestureRecognizer *panRec = [[UIPanGestureRecognizer alloc]initWithTarget:self action:#selector(handlePan:)];
[[thisTaskController view] addGestureRecognizer:panRec];
In the tiggered action triggered using the gesture recognizer I am able to get the view from the parameter using recognizer.view
- (IBAction)handlePan:(UIPanGestureRecognizer *)recognizer {
UIView *touchedView = [[UIView alloc]init];
touchedView = (UIView*)[recognizer view];
...
}
However what I really need is the underlying UIViewController of the view touched. How can I get a reference to the UIViewController that contains this view instead of only the UIView?
I would say that it is more a design issue than just getting a reference. So I would follow several simple advises:
Owner should catch events from its view. I.e. TaskUIViewController sould be a target to UIPanGestureRecognizer which you added to its view.
If a controller has a sub-controller and waits from its sub-controller some responses - implement this as delegate.
You have memory leak in your "handlePan:" method.
Here is a skeleton to solve your issue:
#protocol CallbackFromMySubcontroller <NSObject>
- (void)calbackFromTaskUIViewControllerOnPanGesture:(UIViewController*)fromController;
#end
#interface OwnerController : UIViewController <CallbackFromMySubcontroller>
#end
#implementation OwnerController
- (id)init
{
...
TaskUIViewController *thisTaskController = [[TaskUIViewController alloc] init];
...
}
- (void)viewDidLoad
{
...
[self.view addSubview:thisTaskController.view];
...
}
- (void)calbackFromTaskUIViewControllerOnPanGesture:(UIViewController*)fromController
{
NSLog(#"Yahoo. I got an event from my subController's view");
}
#end
#interface TaskUIViewController : UIViewController {
id <CallbackFromMySubcontroller> delegate;
}
#end
#implementation TaskUIViewController
- (id)initWithOwner:(id<CallbackFromMySubcontroller>)owner
{
...
delegate = owner;
...
}
- (void)viewDidLoad
{
UIPanGestureRecognizer *panRec = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePan:)];
[self.view addGestureRecognizer:panRec];
[panRec release];
}
- (void)handlePan:(UIPanGestureRecognizer *)recognizer {
...
[delegate calbackFromTaskUIViewControllerOnPanGesture:self];
...
}
#end
[touchedView nextResponder] will return the UIViewController object that manages touchedView (if it has one) or touchedView's superview (if it doesn’t have a UIViewController object that manages it).
For more information, see the UIResponder Class Reference. (UIViewController and UIView are subclasses of UIResponder.)
In your case, since you happen to know that touchedView is your viewController's view (and not, for instance, a subview of your viewController's view), you can just use:
TaskUIViewController *touchedController = (TaskUIViewController *)[touchedView nextResponder];
In the more general case, you could work up the responder chain until you find an object of kind UIViewController:
id aNextResponder = [touchedView nextResponder];
while (aNextResponder != nil)
{
if ([aNextResponder isKindOfClass:[UIViewController class]])
{
// we have found the viewController that manages touchedView,
// so we break out of the while loop:
break;
}
else
{
// we have yet to find the managing viewController,
// so we examine the next responder in the responder chain
aNextResponder = [aNextResponder nextResponder];
}
}
// outside the while loop. at this point aNextResponder points to
// touchedView's managing viewController (or nil if it doesn't have one).
UIViewController *eureka = (UIViewController *)aNextResponder;

viewdidload issue xcode 4.2

i just learn how to change switch between views with push and pop.
now, to my second view i add a label witch i wand to change her value every time my second view is push.
i add the label, connect her to my file owner's and i use viewdidload to change her value.
when i entered to my second view nothing is happed. but when i use viewdidapper all work perfect(but it take a second until the label value is update).
my code is:
mysecondviewcontroller.h:
#interface SecondViewController : UIViewController
{
IBOutlet UILabel *textLabel;
NSString *label;
}
#property (copy) NSString *label;
#end
mysecondviewcontroller.m(ofcourse i synthesize label):
-(void)viewDidAppear:(BOOL)animated
{
textLabel.text = label;
NSLog(#"viewdidapper2");
}
- (void)viewDidLoad
{
textLabel.text = label;
[super viewDidLoad];
NSLog(#"viewdidload2");
// Do any additional setup after loading the view from its nib.
}
my firstviewcontroller.m(IBAction):
- (IBAction)pushViewController:(id)sender
{
static int count = 1;
SecondViewController *secondVieController = [[SecondViewController alloc] init];
[self.navigationController pushViewController:secondVieController animated:YES];
secondVieController.title = #"second";
secondVieController.label = [NSString stringWithFormat:#"number: %d", count];
count++;
}
what is the problem in my viewdidload?
thanks!
If you're using viewDidLoad, you need to call the super function before doing anything else.
- (void)viewDidLoad
{
[super viewDidLoad];
textLabel.text = label;
NSLog(#"viewdidload2");
// Do any additional setup after loading the view from its nib.
}
I think that there is another issue, you are setting secondVieController.label after pushing the view controller, but this means at the time that viewDidLoad runs, secondVieController.label is still empty. This should fix it.
- (IBAction)pushViewController:(id)sender
{
static int count = 1;
SecondViewController *secondVieController = [[SecondViewController alloc] init];
secondVieController.title = #"second";
secondVieController.label = [NSString stringWithFormat:#"number: %d", count];
[self.navigationController pushViewController:secondVieController animated:YES];
count++;
}
If you Want to Update Label Every Time when View Loaded Then You have to Write the code in to Viewwillappear Method.

Calling SEL from parentViewController in iOS

I have a ViewController in which I create a Modal ViewController. I have a SEL value in my modal that I set when it is being instantiated from the parent.
setDateViewController.selectorName = #selector(myMethod:);
In my modal I am trying to call this SEL like:
[[self parentViewController] performSelector:self.selectorName withObject:selectedDate afterDelay:.5];
{selectedDate} is obviously a value from my modal.
I don't get any errors or stack, however, this SEL (method) on my parent is never being called. For some reason I think this should work, but something tells me I'm way off track.
Thanks.
I guess [self parentviewcontroller] is not returning anything.
Try UiviewController* v = [self parentviewcontroller]; and check if is nil. Most probably it should be nil. Else if its was pointing to another object of different class then it would have crashed. Please do one thing. YOu should set bot the object and the methd you need to call. IT will solve any issues if it has any.
setDateViewController.selectorDelegate = self;
setDateViewController.selectorName = #selector(myMethod:);
call like this from parent class. So you can dynamically specify the method and the object you want to call gives more flexibility.
and use,
[selectorDelegate performSelector:self.selectorName withObject:selectedDate afterDelay:.5];
this should solve any issues.
Perhaps you would consider added a delegate protocol to your modal that will allow it to call the method on the parent.
Quick (untested) example:
// MyController.h
#protocol MyControllerDelegate;
#interface MyController : UIViewController
{
id<MyControllerDelegate> delegate;
}
#end
#protocol MyControllerDelegate <NSObject>
- (void)methodToCall:(id)sender;
#end
// MyControler.m
#implementation MyController
- (void) loadView
{
[super loadView];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(20.0f, 20.0f, 50.0f, 30.0f);
[btn setTitle:#"blah" forState:UIControlStateNormal];
[btn addTarget:self.delegate
action:#selector(methodToCall:)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
#end
// ParentController.h
#interface ParentController : UIViewController<MyControllerDelegate>
{
}
#end
// ParentController.m
#implementation ParentController
- (void)methodToCall:(id)sender
{
NSLog(#"HERE");
}
#end
Just make sure when you are creating your modal controller you set it's delegate to self on the parent:
MyController *controller = [[MyController alloc] init];
controller.delegate = self;
[self presentModalViewController:controller animated:YES];