Modal viewController presented from UITabBarController - iphone

I have a class that is a subclass of UITabBarController which contains 4 child viewControllers. I've added a button similar to RedLaser, Instagram, Path, DailyBooth, and other apps. Mine is like the top example here:
This button calls a method in the TabBarController which presents a modal viewController. When it's dismissed, the NavigationControllers in the currently selected viewController starts to behave strangely. The pop animation is all messed up and other small bugs happen until you select another tab on the tabBar. Then the animations are fine until the viewController is presented again.
I'm sure it's because I'm dismissing it incorrectly, but I'm not sure how this is to be done.
this is my code in the TabBarController:
-(void)showScanner {
ZBarReaderViewController *reader = [[ZBarReaderViewController alloc] init];
reader.readerDelegate = self;
reader.supportedOrientationsMask = ZBarOrientationMaskAll;
ZBarImageScanner *scanner = reader.scanner;
[scanner setSymbology:ZBAR_I25
config:ZBAR_CFG_ENABLE
to:0];
[scanner setSymbology:ZBAR_QRCODE
config:ZBAR_CFG_ENABLE
to:0];
[reader setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
[self presentModalViewController:reader
animated:YES];
[reader release];
//[self playBeep];
}
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
id<NSFastEnumeration> results = [info objectForKey:ZBarReaderControllerResults];
ZBarSymbol *symbol = nil;
for (symbol in results)
break;
NSString *barcode = symbol.data;
UINavigationController *searchNavController = [[self viewControllers] objectAtIndex:1];
WLSearchViewController *searchVC = [searchNavController.viewControllers objectAtIndex:0];
// WLSearchViewController *searchVC = [[self viewControllers] objectAtIndex:1];
//[searchNavController popToRootViewControllerAnimated:NO];
[self setSelectedViewController:searchNavController];
[self dismissModalViewControllerAnimated:YES];
[self playBeep];
[searchVC handleSearchForTerm:barcode];
}
-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[self dismissModalViewControllerAnimated:YES];
}

Found what was wrong, figured I'd post this to help anyone else who's facing this.
I had overridden a viewDidAppear:animated: in my tabBarController but I didn't call [super viewDidAppear:animated:]
Added that and everything was better!

Related

Viewcontroller not appearing since iOS7

Edit - I solved this myself - see the notes at the bottom
When using iOS7 on Xcode 5, I am using an option to take an image from a camera, or from the photo library, once the image is chosen (or a new picture taken) the view should flip over to the next screen.
This does not happen on the iPhone running iOS7, it works fine on the iPad, but the method is slightly different, but it does appear to be iPhone only problem on iOS7.
here is the code used, for example, on the choose image from library function;
-(void) choosePic {
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeSavedPhotosAlbum]) {
UIImagePickerController *cameraUI = [[UIImagePickerController alloc] init];
cameraUI.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
cameraUI.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType: UIImagePickerControllerSourceTypeSavedPhotosAlbum];
cameraUI.allowsEditing = NO;
cameraUI.delegate = self;
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
_popover = [[UIPopoverController alloc] initWithContentViewController:cameraUI];
[_popover presentPopoverFromRect:btnLibrary.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
else
[self presentModalViewController: cameraUI animated: YES];
}
}
Also, the code once picker is finished;
- (void) imagePickerController: (UIImagePickerController *) picker didFinishPickingMediaWithInfo: (NSDictionary *) info {
//Disable buttons
[[UIApplication sharedApplication] setStatusBarHidden:YES];
[self disableButtons];
//Get image
self.originalImage = (UIImage *) [info objectForKey: UIImagePickerControllerOriginalImage];
//Dismiss
if(_popover)
{
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
[_popover dismissPopoverAnimated:YES];
_popover = nil;
}
}
else
[picker dismissModalViewControllerAnimated: YES];
//Next
[self performSelector: #selector(nextScreen) withObject:nil afterDelay:0.5];
}
I fixed this by switching out;
[picker dismissModalViewControllerAnimated: YES];
With
[picker dismissViewControllerAnimated:NO completion:nil];
First you need to make sure that logic reaches the correct place it's intended to, try setting a breakpoint or NSLog before the iPhone's specific line, try this (You also missed curled braces, added them here) :
-(void) choosePic {
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeSavedPhotosAlbum]) {
UIImagePickerController *cameraUI = [[UIImagePickerController alloc] init];
cameraUI.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
cameraUI.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType: UIImagePickerControllerSourceTypeSavedPhotosAlbum];
cameraUI.allowsEditing = NO;
cameraUI.delegate = self;
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
_popover = [[UIPopoverController alloc] initWithContentViewController:cameraUI];
[_popover presentPopoverFromRect:btnLibrary.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}else{
NSLog(#"Checkpoint !");
[self presentModalViewController: cameraUI animated: YES];
}
} }

UIImagePickerController: Modal and Push Seague

I saw a strange behaviour today. I was trying to open uiimagepickercontroller from a viewcontroler called lets say "BloodWingViewController (subclass of viewcontroller)". Here is the code to display picker:
if (self.picker == nil) {
[SVProgressHUD showWithStatus:#"Loading picker..."];
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^{
self.picker = [[[UIImagePickerController alloc] init] autorelease];
self.picker.delegate = self;
self.picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
self.picker.allowsEditing = NO;
dispatch_async(dispatch_get_main_queue(), ^{
[self.navigationController presentModalViewController:picker animated:YES];
[SVProgressHUD dismiss];
});
});
} else {
[self.navigationController presentModalViewController:picker animated:YES];
}
Well above code works absolutely fine, no problem with that. The strange thing i saw was if i get into this so called "BllodWingViewController" through push seague and try to open picker then it works. But if i get into again so called "BllodWingViewController" through modal seague and try to open picker then it doesnt work at all. No picker opens up. Can u explain me the reason behind this ? And How to overcome this issue since i have to open picker from viewcontroller that has been exec via modal seague connection.
Sorry for my english if it confuses you :P
EDIT:
- (IBAction)onPhotoPickerClick:(id)sender {
if (self.picker == nil) {
[SVProgressHUD showWithStatus:#"Loading picker..."];
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^{
self.picker = [[[UIImagePickerController alloc] init] autorelease];
self.picker.delegate = self;
self.picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
self.picker.allowsEditing = NO;
dispatch_async(dispatch_get_main_queue(), ^{
[self.navigationController presentModalViewController:picker animated:YES];
[SVProgressHUD dismiss];
});
});
} else {
[self.navigationController presentModalViewController:picker animated:YES];
}
}
#import <UIKit/UIKit.h>
#interface EditStudentViewController : UIViewController{
UIImagePickerController * picker;
}
(IBAction)onPhotoPickerClick:(id)sender;
#property (retain, nonatomic) UIImagePickerController * picker;
#end
Now when i am coming to EditStudentViewController using push segue connection, onPhotoPickerClick is working, means photolibary shows up and i can select images. But when i come to EditStudentViewController from previous viewcontroller then photolibary doesnt shows up at all.
Thanks.

trying to show a new screen after image is scanned

I am running into an issue that seems so simplistic, is frustrating. I am using the zbar library to play around with scanning qr-codes. Here is my code:
- (IBAction)scanButtonTapped:(id)sender {
// ADD: present a barcode reader that scans from the camera feed
ZBarReaderViewController *reader = [ZBarReaderViewController new];
reader.readerDelegate = self;
reader.supportedOrientationsMask = ZBarOrientationMaskAll;
reader.showsZBarControls = NO;
UIButton *overlay = [UIButton buttonWithType:UIButtonTypeCustom];
overlay.frame = CGRectMake(0, 0, 320, 480);
[overlay setImage:[UIImage imageNamed:#"CameraCover.png"] forState:UIControlStateNormal];
reader.cameraOverlayView = overlay;
overlay.userInteractionEnabled = YES;
[overlay addTarget:self action:#selector(beginScanning:) forControlEvents:UIControlEventTouchUpInside];
ZBarImageScanner *scanner = reader.scanner;
// TODO: (optional) additional reader configuration here
// EXAMPLE: disable rarely used I2/5 to improve performance
[scanner setSymbology: ZBAR_I25
config: ZBAR_CFG_ENABLE
to: 0];
// present and release the controller
[self presentModalViewController: reader
animated: NO];
[reader release];
}
- (void) imagePickerController: (UIImagePickerController*) reader
didFinishPickingMediaWithInfo: (NSDictionary*) info
{
// ADD: get the decode results
id<NSFastEnumeration> results =
[info objectForKey: ZBarReaderControllerResults];
ZBarSymbol *symbol = nil;
for(symbol in results)
// EXAMPLE: just grab the first barcode
break;
// EXAMPLE: do something useful with the barcode data
resultText.text = symbol.data;
// EXAMPLE: do something useful with the barcode image
resultImage.image =
[info objectForKey: UIImagePickerControllerOriginalImage];
// ADD: dismiss the controller (NB dismiss from the *reader*!)
[reader dismissModalViewControllerAnimated: YES];
[self pushNewScreen];
}
-(void) pushNewScreen
{
MainViewController *mainView = [[MainViewController alloc] initWithNibName:#"MainViewController" bundle:nil];
[self presentModalViewController:mainView animated:YES];
[mainView release];
}
The problem is, when pushNewScreen is called, mainView is not shown... I have gone through each line with the debugger and every line in pushNewScreen is called. Any ideas?
Instead of [self pushNewScreen]; use [self performselector:#selector(pushNewScreen) after delay:0.5f];
It will solve the problem. If not, increase the delay timing.
Thanks to A-Live, I was able to solve it using
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion
instead. Hope this helps someone else!

Issue with dismissModalViewController

I've got a problem when i dismiss a modal view:
I've got a tabBar with five tabs.
I'm on the fourth tab and i display a modal view.
When i dismiss it. I go on the first tab but i would like to stay on the fourth.
To show the modal I call this method, in the parent controller:
[self presentModalViewController:controller animated:YES];
To hide the modal I call this method, in the parent controller:
[self dismissModalViewControllerAnimated:YES];
I already try to call self.tabBarController/self.navigationController methods instead of self method but it's the same issue.
Someone has an idea?
EDIT:
I call the methods in the fourth tab's controller.
This is the context:
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
UIImagePickerController *imgPicker = [[UIImagePickerController alloc] init];
imgPicker.allowsEditing = NO;
imgPicker.delegate = self;
switch (buttonIndex) {
case 0: {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:kMobiglissFromPicker];
imgPicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentModalViewController:imgPicker animated:YES];
break;
}
case 1: {
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:kMobiglissFromPicker];
imgPicker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentModalViewController:imgPicker animated:YES];
}
break;
}
}
}
- (void)imagePickerController:(UIImagePickerController *)imgPicker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *origin = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
UIImage *photo = [origin thumbnailImage:280
transparentBorder:0.0
cornerRadius:0.0
interpolationQuality:kCGInterpolationHigh];
[icon replaceImageWithImage:photo];
[serverProxy updateProfileAvatar:photo];
[self dismissModalViewControllerAnimated:YES];
imgPicker.delegate = nil;
}
- (IBAction)editAvatar:(id)sender {
NSString *camera = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera] ? [WPLanguage get:#"SignupPhotosheetCamera"] : nil;
UIActionSheet *photoSheet = [[UIActionSheet alloc] initWithTitle:[WPLanguage get:#"SignupPhotosheetTitle"]
delegate:self
cancelButtonTitle:[WPLanguage get:#"CANCEL"]
destructiveButtonTitle:nil
otherButtonTitles:[WPLanguage get:#"SignupPhotosheetGallery"], camera, nil];
[photoSheet showInView:self.view];
}
Just a guess (you need to add more details): Does your viewController, which implements the UITabBarDelegate, set the selected item on viewWillAppear: (or one of the other methods called?

iPhone app crash

I have a problem with my application. It crashes after few times of working with images and I have no idea why.
I have a TabBar, in one item of TabBat I have a navigation controller. In the root controller of that navigation I have a two buttons. One button is to get an image from camera or photo library, the second button is to get an image from saved images in the app. With selected image I go to next view controller (SelectImageViewController).
With the first button I use that code:
- (void) showImagePickerWithSourceType:(NSInteger) sourceType
{
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = sourceType;
picker.allowsEditing = NO;
[self presentModalViewController:picker animated:YES];
[picker release];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *selectedImage = (UIImage *)[info objectForKey:#"UIImagePickerControllerEditedImage"];
if (selectedImage == nil)
selectedImage = (UIImage *)[info objectForKey:#"UIImagePickerControllerOriginalImage"];
[[picker parentViewController] dismissModalViewControllerAnimated:YES];
SelectImageViewController *selectImageViewController = [[[SelectImageViewController alloc] initWithImage:selectedImage] autorelease];
[self.navigationController pushViewController:selectImageViewController animated:YES];
}
With the second button I use:
DocumentsViewController *documentsViewController = [[[DocumentsViewController alloc] init] autorelease];
[self.navigationController pushViewController:documentsViewController animated:YES];
DocumentsViewController is a TableViewController with list of images, when I select one image than I go to the SelectImageViewController.
In SelectImageViewController I make some image processing and then go to next view controller where I make another image processing.
Here is some code from SelectImageViewController:
- (id) initWithImage:(UIImage *) image
{
self = [super init];
if (!self) return nil;
self.originalImage = image;
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor grayColor];
[NSThread detachNewThreadSelector:#selector(processImage) toTarget:self withObject:nil];
}
- (void) processImage
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
self.originalImage = [ImageHelper scaleAndRotateImage:self.originalImage toSize:CGSizeMake(1500, 1500)];
self.processedImage = [ImageHelper scaleImage:self.originalImage maxWidth:320 maxHeight:367];
[self performSelectorOnMainThread:#selector(finish) withObject:nil waitUntilDone:NO];
[pool release];
}
- (void) finish
{
imageView = [[UIImageView alloc] initWithImage:self.processedImage];
imageView.center = self.view.center;
[self.view addSubview:imageView];
[self.view sendSubviewToBack:imageView];
[NSThread detachNewThreadSelector:#selector(processImage2) toTarget:self withObject:nil];
}
- (void) processImage2
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSArray *corners = [OpenCV processImage:self.processedImage];
[self performSelectorOnMainThread:#selector(finish2) withObject:nil waitUntilDone:NO];
[pool release];
}
In the SelectImageViewController I have one button and when I click it I process the original image and then go to the next view controller.
In the last view controller in viewDidLoad method I process one more time the image.
I know that all method for image processing take a lot of memory and some time (especially that my original image which I use often is not scaled), but the application also crashes when I only select an image from photo library and go to SelectImageViewController. Maybe I shouldn't use a navigation controller? Has anybody an idea what can be wrong?
Thanks for any help.
Take care about the autorelease. Functions usually return autorelease objects. You are within an autorelease pool so, it is possible that the image wont exists when you call the last selector. Try assigning the images by using de setter method
[self setProcessedImage:[ImageHelper scaleImage:self.originalImage maxWidth:320 maxHeight:367]];
only if you have declared your variable as an instance property with retain or copy, it will retain the image.
Use NSZombieEnabled to see what happens. It seems to be a classic problem of a freed object.