I am using custom camera with the help of UIImagePickerController. I am subclassing the UIImagePickerController class and using without present/dismiss. We are just opening the customise camera view and taking picture. After sometime by clicking camera takepicture method gets called and app is getting crash. No delegate method called during this. My code is this:
-(void)viewDidLoad
{
if([UIImagePickerController isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceRear] && self.camType==2)
{
self.sourceType=UIImagePickerControllerSourceTypeCamera;
self.cameraDevice=UIImagePickerControllerCameraDeviceRear;
self.showsCameraControls = NO;
self.wantsFullScreenLayout=NO;
self.navigationBar.hidden=NO;
self.cameraOverlayView = mainView;
}
}
else
{
self.navigationBar.hidden=YES;
self.sourceType=UIImagePickerControllerSourceTypePhotoLibrary;
[notAllowBtn setHidden:TRUE];
[cmView setHidden:TRUE];
}
self.delegate=self;
[self.view addSubview:cmView];
}
-(void)cameraTakePic {
if([UIImagePickerController isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceRear]) {
[self takePicture];
}
}
- (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info{
if (![info objectForKey:#"UIImagePickerControllerOriginalImage"]) {
NSArray *arr=[[appDel navController] viewControllers];
id obj=[arr lastObject];
UIViewController *objContr=((UIViewController *)obj);
objContr.navigationController.navigationBar.userInteractionEnabled = YES;
[clickBtn setEnabled:YES];
return;
}
UIImage* image = nil;
UIImage *imageTemp = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
}
From the Apple UIImagePickerController class reference:
The UIImagePickerController class supports portrait mode only. This
class is intended to be used as-is and does not support subclassing.
The view hierarchy for this class is private and must not be modified,
with one exception. You can assign a custom view to the
cameraOverlayView property and use that view to present additional
information or manage the interactions between the camera interface
and your code.
You shouldn't subclass the UIImagePickerController class, instead you should use AVFoundation and make your custom capture methods.
Related
i have created a simple app with two buttons and one uiimageview.
One button takes a photo from photo library and puts it on uiimageview.
When the user adds another photo the old one should be saved and then user can swipe between these two photos.
another button takes a photo and put it on uiimageview.
So now i'm really confused about swiping between photos. I read that uiimageview can contain only one image. Also, i read that i need to add uiScrollView to UiImageView, but i don't know how they work together.
should i delete my UIImageView and then create ScrollView instead of it?
Here is my code
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (IBAction)pickPhoto:(id)sender {
picker1 = [[UIImagePickerController alloc]init];
picker1.delegate = self;
[picker1 setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
[self presentViewController:picker1 animated:YES completion:NULL];
}
- (IBAction)takePhoto:(id)sender {
picker2 = [[UIImagePickerController alloc]init];
picker2.delegate = self;
if([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera]){
}
else{
NSLog(#"not avaialbe");
}
[self presentViewController:picker2 animated:YES completion:NULL];
}
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
image = [info objectForKey:UIImagePickerControllerOriginalImage];
[self.imageView setImage:image];
[self dismissViewControllerAnimated:YES completion:NULL];
}
- (void) imagePickerControllerDidCancel:(UIImagePickerController *)picker
{
[self dismissViewControllerAnimated:YES completion:NULL];
}
UPDATE
So i have added a method that allows user to swipe left or right and he can see different pictures, however, i had to hard code my images into the code. But i want to select images from the photo library, then these images will be saved in the array and then if user adds more pictures he has a choice to swipe through his old images.
Here is my code for swiping through the images
- (IBAction)Swipe:(id)sender {
NSArray *images = [[NSArray alloc]initWithObjects:#"ayat.png", #"qwe.png",#"4444", #"15", nil];
UISwipeGestureRecognizerDirection direction = [(UISwipeGestureRecognizer *) sender direction];
switch(direction)
{
case UISwipeGestureRecognizerDirectionLeft:
imageIndex++;
break;
case UISwipeGestureRecognizerDirectionRight:
imageIndex--;
break;
default:
break;
}
imageIndex = (imageIndex <0)?([images count] -1 ):
imageIndex % [images count];
self.imageView.image = [UIImage imageNamed:[images objectAtIndex:imageIndex]];
}
but here i added pictures to my project.
It's true that a UIImageView can display only a single image.
There are various ways to handle this. One would be to use a UIPageViewController. That would enable you to set up side-swipe based paging between pages of content. There is a sample app from Apple called PhotoScroller (it used to be linked from the Xcode help system. With Xcode 6, apple seems to have removed all sample code. You'll have to search the net for the sample app. That app also includes tiled rendering, which is likely overkill for your application, but it does show how to set up a page view controller.
You could also use a UICollectionView, or create your own custom view that manages a set of views.
Actually now that I think about it a UICollectionView set up for paging might be your best bet.
I am presently using UIImagePicker and my app crashes on iOS 8 with the following workflow:
Start the camera, zoom it which shows the zoom slider below and then take a picture. Select Use Photo and app crashes.
After looking more into the crash "didHideZoomSlider" message is sent to the deallocated instance of image picker view.
Here is my code:
imagePicker = [[UIImagePickerController alloc] init];
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePicker.mediaTypes = [[NSArray alloc] initWithObjects:(NSString *)kUTTypeImage, nil];
imagePicker.allowsEditing = YES;
imagePicker.delegate = self;
[myController presentViewController:imagePicker animated:animated completion:nil];
I tried a couple of things. My controller holds a strong reference to the image picker, I tried making it a weak reference and the app still crashes. Also I need a strong reference so I actually cannot make it weak.
Although this looks like an Apple bug and someone has already logged it (http://openradar.appspot.com/18762927) I wanted to try the workaround they are using. However I am not able to get to "CAMZoomSlider" through UIImagePicker's instance.
Does anyone know how to get to CAMZoomSlider?
I was able to clear the CAZoomSlider delegate by doing the following in a subclassed UIImagePickerController class. And sure enough, it seems to have resolved the crash.
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self clearZoomSliderDelegate:self.view.subviews];
}
- (void)clearZoomSliderDelegate:(NSArray*)subviews
{
for (UIView *subview in subviews)
{
if ([subview isKindOfClass:NSClassFromString(#"CAMZoomSlider")])
{
if ([subview respondsToSelector:#selector(setDelegate:)]) {
[subview performSelector:#selector(setDelegate:) withObject:nil];
}
return;
}
else if (subview.subviews != nil) {
[self clearZoomSliderDelegate:subview.subviews];
}
}
}
I have a question about CvPhotoCamera (OpenCV) in the iOS App.
I have a myViewController1: in this viewController I push a mySecondView controller.
In this second View Controller I use CvPhotoCamera:
I have a UIImageViewController.
In viewDidLoad I have this code:
- (void)viewDidLoad
{
[super viewDidLoad];
_photoCamera = [[CvPhotoCamera alloc] initWithParentView:imageView];
_photoCamera.defaultAVCaptureSessionPreset = AVCaptureSessionPresetPhoto;
_photoCamera.defaultAVCaptureVideoOrientation = AVCaptureVideoOrientationPortrait;
[_photoCamera setDefaultAVCaptureDevicePosition:AVCaptureDevicePositionBack];
_photoCamera.delegate = self;
[_photoCamera start];
}
in viewDidDisappear I have this code:
- (void) viewDidDisappear:(BOOL)animated
{
[_photoCamera stop];
}
I use CvPhotoCamera to take a photo from camera using the method:
- (IBAction)actionStart:(id)sender;
{
[_photoCamera takePicture];
}
The my problem is this:
When I push this second ViewController and I tap on back button on Nav bar I have some memoryWarning and the app crashes ..always!!!
I used also the profile Xcode tool to manage memory allocation or memory leak but I do not see anything strange.
Is correct this use of CvPhotoCamera obj?
Since the iOS7 upgrade, I have a weird behaviour of the UIImagePickerController. In this application I am using the UIImagePickerController with a cameraOverlayView.
In iOS6 I called the UIImagePickerController using the following code:
_picker = [[UIImagePickerController alloc] init];
if ([UIImagePickerController isCameraDeviceAvailable:UIImagePickerControllerCameraDeviceRear]) {
_picker.sourceType = UIImagePickerControllerSourceTypeCamera;
_picker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
_picker.cameraDevice = UIImagePickerControllerCameraDeviceRear;
_picker.showsCameraControls = NO;
_picker.navigationBarHidden = NO;
_picker.toolbarHidden = YES;
_picker.wantsFullScreenLayout = YES;
_overlayViewController = [[OverlayViewController alloc] init];
_overlayViewController.picker = _picker;
_overlayViewController.frameSize = self.frameSize;
_overlayViewController.delegate = self;
_picker.cameraOverlayView = _overlayViewController.view;
}
else {
_picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
}
_picker.delegate = self;
Where the OverlayViewController is an UIViewController, with a transparent background which draws some custom controls on screen.
But now in iOS 7 the camera is drawn through the statusbar and a black bar appears beneath the live camera view.
I can solve this by applying a CGAffineTransformMakeTranslation to the cameraViewTransform property of the UIImagePickerController, but why is this like this?
In iOS 7, by default UIViewController views take up the entire screen area including the status bar.
wantsFullScreenLayout
is deprecated and ignored. In some cases, this fix works (in the view controller class):
if ([self respondsToSelector:#selector(setEdgesForExtendedLayout:)]) {
[self setEdgesForExtendedLayout:UIRectEdgeNone];
}
In other cases, it's a bit more complicated. It's late here, so see how you go with it. Helpful things to note - in a UIViewController, the following code will give the correct statusbar height on both iOS 6 and iOS 7, should it come to having to align things using CGRect math:
if (UIDeviceOrientationIsLandscape(self.interfaceOrientation)) {
statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.width;
} else {
statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height;
}
And then don't forget that in Interface Builder, there are the new "iOS 6 delta" adjustments that allow you to design for iOS 7 and then use offsets to correct for iOS 6.
Anyhow, let me know how you go.
My understanding of the issue, based on a few other SO threads and such, is that UIImagePickerController does not do what we'd expect in terms of managing the status bar via [UIViewController -prefersStatusBarHidden].
This means you either have to disable view controller status bar management entirely, via plist, or figure out a way to get UIImagePickerController to do what we want. On the assumption that you're not looking for the former, I can say I've had success in the latter by putting the picker in a wrapper controller that does what I want (but fall back to your previous code if you still need to detect/support iOS6):
#interface PickerContainer : UIViewController
#property ( nonatomic, weak ) UIImagePickerController* picker;
#end
#implementation PickerContainer
- (void) setPicker: (UIImagePickerController*) picker
{
[self addChildViewController: picker];
[picker didMoveToParentViewController: self];
self->_picker = picker;
}
- (void) viewDidLoad
{
[super viewDidLoad];
self.picker.view.frame = self.view.bounds;
[self.view addSubview: self.picker.view];
}
// Will have no effect in ios6 -- see [-init] for that option
- (BOOL) prefersStatusBarHidden { return YES; }
- (id) init
{
if ( ! ( self = [super init] ) ) return nil;
if ( detectThatThisIsIos6() ) self.wantsFullScreenLayout = YES;
return self;
}
#end
This will work for you, scaled camera, you will have a black bar at the bottom but it will get overlayed by tool bar
https://stackoverflow.com/a/15803947
I use standart image picker to make some camera photo.
When user makes photo image picker shows him the Preview screen with 2 buttons "Retake" and "Use".
How to detect that Preview screen is active now or "Retake" button pressed? Is it possible ? Are the useful properties or events? Something like when image source is library the is property - allows editing, which shows similar screen .
UIImagePickerController * imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
A bit after the fact, but maybe someone is still seeking this answer like I was. If you want continue using the native camera controls, you can check the subviews of the ImagePickerController to determine if the post-record view is showing.
BOOL videoTaken = NO;
for (UIView *aView in self.imagePickerController.view.subviews[0].subviews[0].subviews[0].subviews)
{
if ([aView isKindOfClass:NSClassFromString(#"PLTileContainerView")])
{
videoTaken = YES;
break;
}
}
The "PLTileContainerView" is the subview that contains the editing slider that lets you view your video frame by frame, so if it's present, that means your video has already recorded.
For use:
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
[picker dismissModalViewControllerAnimated:NO];
NSString *type = [info objectForKey:#"UIImagePickerControllerMediaType"];
if ([type isEqualToString:#"public.movie"]) {
} else {
UIImage *image = [info objectForKey:#"UIImagePickerControllerOriginalImage"];
}
}
For Cancel you don't have a way of detecting it (other than subclassing UIImagePickerController, which may be prohibited, or other way that I'm not aware), but for sure the second cancel is detectable :
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[picker dismissModalViewControllerAnimated:YES];
}