Search
Recommended for You

Creating a Full-Screen Camera Preview


I'm not big on the whole Image Picker Camera interface. I hate how slow it is and how it prevents you from scraping the screen. So here's my work around. In the following code, I scan down the UIImagePicker presentation to find my way to the actual preview window.

First, I build my camera controller. I make sure that the camera type source is available:

#define SOURCETYPE UIImagePickerControllerSourceTypeCamera
if ([UIImagePickerController isSourceTypeAvailable:SOURCETYPE])	self.sourceType = SOURCETYPE;

Next, I add a delayed call to tell the image picker to update itself. This allows time for the image picker to load before I start messing with its views. I'm using a Navigation Controller here because I need a "Snap" button as part of my interface.

CameraController *cam = [[CameraController alloc] init];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:cam];
[cam performSelector:@selector(updateView) withObject:NULL afterDelay:2.0f];

The update adds a bar button item to the navigation bar and removes the overlay leaving just the preview displayed:

- (void) updateView
{
	self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc]
											   initWithTitle:@"Snap" 
											   style:UIBarButtonItemStylePlain 
											   target:self 
											   action:@selector(snapIt:)] autorelease];
	
	// Remove the overlay
	UIView *plView = [[[[[[self.view subviews] lastObject] subviews] lastObject] subviews] lastObject];
	[[[plView subviews] objectAtIndex:3] removeFromSuperview];
}

This allows me to snap a copy of the screen as desired. This current implementation does not hide or remove the nav bar. It just does a full-screen snap:

- (void) snapIt: (UIBarButtonItem *) button
{	
    [self writeImage:[UIImage imageWithCGImage:UIGetScreenImage()]];
}

I put this all together so I could update "Dress Up" for App Store. I'm not sure, however, that removing the Apple UI elements will qualify to get past Apple's gatekeepers. What do you think? Should customizing an existing UI element like the be a bar to the store? Let me know in the comments.

AddThis Social Bookmark Button
Comments (11)

11 Comments

I believe this definitely violates the spirit of Apple's (stupid) restrictions ;P.

WiFone said:

One could actually also argue the reverse: to ensure a consistent user experience, which Apple seems to welcome or even demand, one should preferably use the same standard UI elements as Apple does.

Chris L said:

Good luck. I've heard of apps getting rejected due to lesser things, like a toolbar being at the top of the screen instead of the standard bottom.

Malcolm Hall said:

Problem here is the photo is only screen res instead of 1MP.

holly said:

It is PLCameraController instead in 2.x

Blain said:

Should customizing an existing UI element like the be a bar to the store?

You know as well as I do that Apple gets blamed when iPhone OS updates happen and applications break. So if they were to change some internal functions or layouts, that only Apple code calls, all well behaved apps will continue to run fine.

Apps that aren't well behaved, and make assumptions that are not only risky to make, but have been explicitly marked as, 'do not assume', and then hurt the experience when the assumptions no longer hold true, well, shouldn't do that.

Calling a function that is undocumented and might go away in 2.2 or 2.3 is one example of not being well-behaved. Blindly navigating and pulling objects from a view hierarchy without knowing what they are except that 'it worked when I tested it' is another.

Generating bug reports with Apple is a good way for them to know which private libraries they should clean up and make public. Placing land mines for the user by depending on an immature and rapidly changing API to not change isn't. Note the irony that, in using private frameworks, it would make Apple's job of making them open to the public harder, because now they can't rename, replace, and refactor things as easily as they should.

I'd even to go so far as saying the sample code has at least two show-stopping bugs.

Warren said:

At a recent San Francisco Tech Talk, an Apple Evangelist demonstrated how to use [[someView subviews] objectAtIndex:1] to tweak VideoPlayback . Sorry, don't have details, at the moment.

The point is, if Apple is showing how to get around their normal controls, then this may not be a show stopper, after all.

Mileage may vary.

Bruce said:

There is a new app called SteadyCam that seems to use direct camera access. Very cool app but I doubt they are following the rules.

Louis said:

I didn't get how it was supposed to work at first, but I figured it out at the end. And I moved the removing of the overlays into viewDidAppear:, so no fumbling with delays/what happens when the controller is "re-appeared".
Here's my write up about how I did it.

lajos said:

I have a small xcode project and some write up to demonstrate some tweaks to the camera interface here: custom UIImagePickerController camera view.

walt said:

I did very much the same thing for our first app, Laser Level. By trial and error I discovered which views I did not want and simply hid them rather than remove them. Apple approved it for the iTunes store, and rightly so I think because no private classes were used.

I think that hiding a view is less risky than removing it, but in either case I do agree that a future OS release could break my code. However our app does say that it requires iPhone OS 2.2 update and will remain that way until I can test Laser Level with the next OS release.

I also submitted enhancement requests to allow developers to remove/customize the big buttons and messages. If Apple's native camera app doesn't have to splash "Take Photo" (or whatever it is) across their screen I don't understand why UIImagePicker has to.

(BTW Erica, I picked up your book when I started and found it really helpful, thanks.)

Leave a comment


Type the characters you see in the picture above.