NSZombie detected that one of the objected is over released in my app and that is causing the app to crash every time when a button is pressed. However, after inspecting the source code of where the over release happens, I couldn't see any obvious code that that may have caused the release. Can xcode release objects automatically without any actual code?
Below are the places reported by the Instrument that has a release event:
-(void) takePicture:(CDVInvokedUrlCommand *)command {
CDVCameraPicker* cameraPicker = [[CDVCameraPicker alloc] init];
self.pickerController = cameraPicker;
CameraOverlayViewController* overlay = [[CameraOverlayViewController alloc] initWithNibName:#"CameraOverlayViewController" bundle:nil];
cameraPicker.sourceType = UIImagePickerControllerSourceTypeCamera;
cameraPicker.cameraOverlayView = overlay.view;
[self.viewController presentViewController:cameraPicker animated:YES completion:nil];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
Any ideas on how to fix the problem? Thanks in advance!
I think CameraOverlayViewController is released.
Try the below code
CameraOverlayViewController* overlay;
-(void) takePicture:(CDVInvokedUrlCommand *)command {
CDVCameraPicker* cameraPicker = [[CDVCameraPicker alloc] init];
self.pickerController = cameraPicker;
overlay = [[CameraOverlayViewController alloc] initWithNibName:#"CameraOverlayViewController" bundle:nil];
cameraPicker.sourceType = UIImagePickerControllerSourceTypeCamera;
cameraPicker.cameraOverlayView = overlay.view;
[self.viewController presentViewController:cameraPicker animated:YES completion:nil];
}
You're creating a CameraOverlayViewController and keeping a reference to it's view, but the CameraOverlayViewController itself is going out of scope when the takePicture: method ends. A view doesn't retain it's view controller. You need to either keep a reference to the CameraOverlayViewController, or if you're only interested in the view object itself, just create a view from the xib file and set the cameraPicker.cameraOverlayView to that view.
EDIT:
For example, in your header file you could make a property:
#property (strong) CameraOverlayViewController *overlay;
and in your method:
-(void) takePicture:(CDVInvokedUrlCommand *)command {
CDVCameraPicker* cameraPicker = [[CDVCameraPicker alloc] init];
self.pickerController = cameraPicker;
self.overlay = [[CameraOverlayViewController alloc] initWithNibName:#"CameraOverlayViewController" bundle:nil];
cameraPicker.sourceType = UIImagePickerControllerSourceTypeCamera;
cameraPicker.cameraOverlayView = self.overlay.view;
[self.viewController presentViewController:cameraPicker animated:YES completion:nil];
}
Once you're done with the camera, you'll want to let go of the reference. So for example:
-(void) cameraPickerFinished {
self.overlay = nil;
}
Related
I'm trying to create a customized UIImagePickerController with the following code.
ECPhotoPickerController.h
#interface ECPhotoPickerController : UIImagePickerController
#property (strong, nonatomic) void(^didFinishSavingPhoto)(NSURL* url, UIImage* image);
#property (strong, nonatomic) void(^didDismissed)(void);
#end
ECPhotoPickerController.m
...
- (void)viewDidLoad {
[super viewDidLoad];
self.sourceType = UIImagePickerControllerSourceTypeCamera;
self.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
self.showsCameraControls = false;
[self setCameraOverlayView:self.overlayView];
self.delegate = self;
}
...
The customized image picker controller will be presented after I tapped a button, which would invoke the following method.
- (void)showImagePicker {
ECPhotoPickerController* vc = [[ECPhotoPickerController alloc] init];
vc.didFinishSavingPhoto = ^(NSURL *url, UIImage *image) {
self.selectedImage = image;
};
vc.didDismissed = ^{
// dismissed
};
[self presentViewController:vc animated:true completion:nil];
}
But the app will only crash on iOS 11 with the log
[UIViewController _setCameraOverlayView:]: unrecognized selector sent to instance 0x108403dd0
and there is anther weird log before the crash.
[] <<<< AVOutputDeviceDiscoverySession (FigRouteDiscoverer) >>>> -[AVFigRouteDiscovererOutputDeviceDiscoverySessionImpl outputDeviceDiscoverySessionDidChangeDiscoveryMode:]: Setting device discovery mode to DiscoveryMode_None (client: ECalligraphy)
The customized image picker class obviously inherit from UIImagePickerController.
And when I initialized it with [[ECPhotoPickerController alloc] init], it should invoke the super class's initialization since I didn't implement the initialization of ECPhotoPickerController.
I'm really confused about this crash.
Any advice will be appreciated.
I final found the reason!
The sourceType should be specified before the view controller start to be
load on iOS 11.
That means, you should set the value of sourceType during the initialization of your customized view controller or do it for the instance before load.
- (instancetype)init { // `initFromNibName` etc. depends on the way you initialize it.
if (self = [super init]) {
self.sourceType = UIImagePickerControllerSourceTypeCamera;
self.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
self.showsCameraControls = false;
self.delegate = self;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
}
Or
- (void)showImagePicker {
ECPhotoPickerController* vc = [[ECPhotoPickerController alloc] init];
vc.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController:vc animated:true completion:nil];
}
I am attempting to pass a variable between to view controllers and then show the new view
I have implemented the following code to pass a variable (without using segue)
viewCameraViewController *viewCamera = [[viewCameraViewController alloc] initWithNibName:#"viewCameraViewController" bundle:nil];
viewCamera.str1 = self.str;
[self.navigationController pushViewController:viewCamera animated:YES];
and then this to show the view
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"cameraView"];
vc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:vc animated:YES completion:NULL];
however when the new view loads the variable is null
here is my viewCamera class
//
// viewCameraViewController.m
// WebView
//
// Created by Admin on 31/10/2015.
// Copyright (c) 2015 Admin. All rights reserved.
//
#import "viewCameraViewController.h"
#interface viewCameraViewController ()
#end
#implementation viewCameraViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.\
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(IBAction)takePhoto:(UIButton *)sender {
if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
UIAlertView *myAlertView = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"Device has no camera"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[myAlertView show];
} else {
UIImagePickerController *picker = [[UIImagePickerController alloc]init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
[self presentViewController: picker animated:YES completion:NULL];
}
}
-(IBAction)selectPhoto:(id)sender {
UIImagePickerController *picker = [[UIImagePickerController alloc]init];
picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentViewController: picker animated:YES completion:NULL];
}
-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *chosenImage = info[UIImagePickerControllerEditedImage];
self.imageView.image = chosenImage;
[picker dismissViewControllerAnimated:YES completion:NULL];
}
-(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[picker dismissViewControllerAnimated:YES completion:NULL];
}
#end
im assuming that this is caused by initialising two instances of the class, one called viewCamera and the other called VC.
can anyone help identify where i am going wrong here and point me in the right direction.
Thanks in advance
If you have a View Controller that is defined in Interface Builder, you don't want to instantiate it with alloc/init, but rather with the method used in your second snippet. Make sure that you have set the class of your view controller in interface builder, and then cast it to your class to set the variable.
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:nil];
YourViewControllerClass *vc = (YourViewControllerClass *)[storyboard instantiateViewControllerWithIdentifier:#"cameraView"];
vc.yourStringVariable = self.str;
vc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentViewController:vc animated:YES completion:NULL];
Note that presentViewController and pushViewController are two different ways of displaying a view controller. The first one presents it modally, the other one pushes it to a navigation controller. You don't want both of these calls.
Update after your update: so, YourViewControllerClass is viewCameraViewController - however, I'd point out that's an oddly named class; class names should start with upper case. Name it CameraViewController instead, is my suggestion. And don't use initWithNib: if you have your view controller defined in a storyboard, just remove that.
I have been searching for a while and can not seem to find a clear way of doing this. Any link I did find is outdated. I am presenting a camera like so
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
//Get the camera
self.imagePicker = [[UIImagePickerController alloc] init];
self.imagePicker.delegate = self;
self.imagePicker.allowsEditing = NO;
self.imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
self.imagePicker.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:self.imagePicker.sourceType];
self.imagePicker.showsCameraControls = NO;
self.imagePicker.wantsFullScreenLayout = YES; //<-- This does not work in iOS7
//set our custom overlay view
[self presentViewController:self.imagePicker animated:NO completion:nil];
}
I have a ViewController connected to an xib named ControllsViewController . I have no idea how to assign it to self.imagePicker.cameraOverlayView = . Can anyone help me here?
You need to instantiate the ControllsViewController using the xib. Assuming you have a xib file called "ControllsViewController" in your main bundle:
ControllsViewController *overlayViewController = [ControllsViewController alloc] initWithNibName:#"ControllsViewController" bundle:nil];
self.imagePicker.cameraOverlayView = overlayViewController.view;
You probably want to assign overlayViewController to a property to keep it around.
So I have this code -
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
self.searchController = [[PlacesViewController alloc]initWithNibName:#"PlacesView" bundle:nil];
NSLog(#"TEXT FIELD DID BEGIN EDITIN");
self.navigationItem.hidesBackButton = YES;
[self.navigationController pushViewController:self.searchController animated:YES];
return NO;
}
The NSLog runs, but my view doesn't appear. This is happening in a controller that has a view that exists in the navigation bar. Like this -
-(void)addSearchBar{
self.searchBarController = [[SearchBarController alloc] initWithNibName: #"SearchBar" bundle: nil];
self.navigationItem.titleView = self.searchBarController.view;
}
where addSearchBar is called in the initWithNibName method.
Why is my view not appearing?
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
searchQuery = [[SPGooglePlacesAutocompleteQuery alloc] init];
searchDetailQuery = [[SPGooglePlacesPlaceDetailQuery alloc] init];
searchQuery.radius = 2000;
shouldBeginEditing = YES;
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
}
return self;
}
I've also proven that the view works because when I do this -
-(void)textFieldDidBeginEditing:(UITextField *)textField{
self.searchController = [[PlacesViewController alloc]initWithNibName:#"PlacesView" bundle:nil];
//may have to be strong.
NSLog(#"SELF VIEW : %#", self.view);
textField.inputView.center = self.view.center;
textField.inputView.bounds = self.view.bounds;
textField.inputView = self.searchController.view;
}
The view appears in place of the keyboard.
You can move the addSearchBar from initWithNibName to viewDidLoad for a try. In fact, usually in the init method, the view doesn't initialize. The view will be lazily initialize when it is first access, usually when you show the view on the screen, and the viewDidLoad method will be call immediately after the view is initialized. So usually the init method only configure data related property, and the view related property usually configured in the viewDidLoad method.
I'm trying to display the image a the camera sees into my own custom view. I DO NOT want to use Apple's own overlay property for UIImagePickerController: cameraOverlayView.
I don't want an overlay, but for it to just display in my particular view. The only way I've been able to do it was creating a subview in my UIView, but doing this doesn't allow me to use any of my own custom buttons I've made over my UIView . My code so far is:
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
[imagePickerController setSourceType:UIImagePickerControllerSourceTypeCamera];
[imagePickerController setShowsCameraControls:NO];
[imagePickerController setEditing:NO];
[imagePickerController setNavigationBarHidden:YES];
[self.videoPreviewView addSubview:[imagePickerController view]];
[imagePickerController viewWillAppear:YES];
where videoPreviewView is the outlet for my UIView!
Any suggestions? Thanks!
I have not tried it your way myself, but I also wanted to create a custom camera view. This might not be what you are looking for, but it is an alternative. I created a custom UIView together with .xib file.
In the .m file you just call the appropriate delegate methods to the ViewController where you instantiated the imagePicker. In this ViewController you then call appropriate methods like takePicture.
This way you can make the overlay look any way you like with the xib file. You can instantiate the image picker
FALKCameraView.h :
#protocol CameraViewDelegate <NSObject>
- (void)cameraPressed;
- (void)buttonPressed;
//etc
#end
#interface FALKCameraView : UIView
#property (nonatomic, assign) NSObject<CameraViewDelegate> *delegate;
//Camera Button pressed- notifies CameraViewDelegate
- (IBAction)cameraPressed:(id)sender;
//Button pressed - notifies CameraViewDelegate
-(IBAction)buttonPressed:(id)sender;
#end
FALKCameraView.m:
#implementation FALKCameraView
#synthesize delegate;
- (IBAction)cameraPressed:(id)sender{
[delegate cameraPressed];
}
-(IBAction)buttonnPressed:(id)sender{
[delegate buttonPressed];
}
#end
FALKCameraViewController.h:
#interface FALKCameraViewController : UIViewController <UIImagePickerControllerDelegate, CameraViewDelegate>
- (void)cameraPressed;
- (void)buttonPressed;
#end
FALKCameraViewController.m:
#interface FALKCameraViewController
#property (strong,nonatomic) UIImagePickerController *imagePicker;
#end
#implementation FALKCameraViewController
#synthesise imagePicker;
-(void)setUpCamera{
if ([UIImagePickerController isSourceTypeAvailable:
UIImagePickerControllerSourceTypeCamera]){
imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType =
UIImagePickerControllerSourceTypeCamera;
imagePicker.showsCameraControls = NO;
imagePicker.allowsEditing = NO;
imagePicker.mediaTypes = #[(NSString *) kUTTypeImage];
NSString *nibName = #"FALKCameraView";
NSArray *nibs = [[NSBundle mainBundle] loadNibNamed:nibName
owner:nil
options:nil];
if([nibs count]){
id nib = [nibs objectAtIndex:0];
if([nib isKindOfClass:[FALKCameraView class]]){
FALKCameraView *view = (FALKCameraView*)nib;
view.delegate = self;
imagePicker.cameraOverlayView = view;
}
}
[self presentViewController:imagePicker
animated:NO completion:nil];
}
}
-(void)cameraPressed:(id)sender{
[imagePicker takePicture];
}
#end
Hope it will work and i just added a single view you can add any custom object to overlayview of the picker
if ([UIImagePickerController isSourceTypeAvailable:
UIImagePickerControllerSourceTypeCamera]){
imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType =
UIImagePickerControllerSourceTypeCamera;
imagePicker.showsCameraControls = NO;
imagePicker.allowsEditing = NO;
NSString *nibName = #"CameraView";
NSArray *nibs = [[NSBundle mainBundle] loadNibNamed:nibName
owner:nil
options:nil];
if([nibs count]){
id nib = [nibs objectAtIndex:0];
if([nib isKindOfClass:[CameraView class]]){
CameraView *view = (CameraView*)nib;
view.delegate = self;
imagePicker.cameraOverlayView = view;
}
}
[self presentViewController:imagePicker
animated:NO completion:nil];
}