Camera

Taking pictures and UIImagePickerController

Now you need a button to initiate the photo-taking process. It would be nice put this button on the navigation bar, but we will need the navigation bar for another button later. Instead, we will create an instance of UIToolbar and place it at the bottom of ItemDetailViewController's view.

A UIToolbar works lot like a UINavigationBar in that you can add UIBarButtonItems to it. However, where a navigation bar has two bar button items, a toolbar has an array of items. You can place as many UIBarButtonItems in a toolbar as can fit on the screen.

By default, a new instance of UIToolbar create in Interface Builder comes with one UIBarButtonItem. Select this bar button item and open the attribute inspector. Change the Identifier to Camera, and the item will show a camera icon.

- (void)takePicture:(id)sender
{
  UIImagePickerController *imagePicker =
  [[UIImagePickerController alloc] init];
  // If our device has a camera, we want to take a picture, otherwise, we
  // just pick from photo library
  if ([UIImagePickerController
    isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
    [imagePicker setSourceType:UIImagePickerControllerSourceTypeCamera];
  } else {
    [imagePicker setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
  }
  // This line of code will generate 2 warnings right now, ignore them
  [imagePicker setDelegate:self];
  // Place image picker on the screen
  [self presentModalViewController:imagePicker animated:YES];
  // The image picker will be retained by ItemDetailViewController
  // until it has been dismissed
  [imagePicker release];
}

When image's picked, delegate handler

- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info
{
  // Get picked image from info dictionary
  UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
  // Put that image onto the screen in our image view
  [imageView setImage:image];
  // Take image picker off the screen -
  // you must call this dismiss method
  [self dismissModalViewControllerAnimated:YES];
}

To get around this problem, we must create a separate store for images. Instead of putting the image
directly into the imageView, we will put it into this store. Then when the ItemDetailViewController’s
view next appears on screen, we’ll have the ItemDetailViewController grab the image from the
image store and put it into its own imageView. In general, this is a best practice: a view controller
should re-populate its view’s subviews with data whenever it is sent the message viewWillAppear:,
eliminating the possibility that a low-memory warning could wipe out its content.

- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info
{
  NSString *oldKey = [possession imageKey];
  // Did the possession already have an image?
  if (oldKey) {
  // Delete the old image
  [[ImageStore defaultImageStore] deleteImageForKey:oldKey];
  }
  UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
  // Create a CFUUID object - it knows how to create unique identifier strings
  CFUUIDRef newUniqueID = CFUUIDCreate (kCFAllocatorDefault);
  // Create a string from unique identifier
  CFStringRef newUniqueIDString =
  CFUUIDCreateString (kCFAllocatorDefault, newUniqueID);
  // Use that unique ID to set our possessions imageKey
  [possession setImageKey:(NSString *)newUniqueIDString];
  // We used "Create" in the functions to make objects, we need to release them
  CFRelease(newUniqueIDString);
  CFRelease(newUniqueID);
  // Store image in the ImageStore with this key
  [[ImageStore defaultImageStore] setImage:image
  forKey:[possession imageKey]];
  // Put that image onto the screen in our image view
  [imageView setImage:image];
  // Take image picker off the screen
  [self dismissModalViewControllerAnimated:YES];
}

and in viewWillAppear:

- (void)viewWillAppear:(BOOL)animated
{
  [super viewWillAppear:animated];
  [nameField setText:[possession possessionName]];
  [serialNumberField setText:[possession serialNumber]];
  [valueField setText:[NSString stringWithFormat:@"%d",
  [possession valueInDollars]]];
  NSDateFormatter *dateFormatter = [[[NSDateFormatter alloc] init]
    autorelease];
  [dateFormatter setDateStyle:NSDateFormatterMediumStyle];
  [dateFormatter setTimeStyle:NSDateFormatterNoStyle];
  [dateLabel setText:
  [dateFormatter stringFromDate:[possession dateCreated]]];
  [[self navigationItem] setTitle:[possession possessionName]];
  NSString *imageKey = [possession imageKey];
  if (imageKey) {
    // Get image for image key from image store
    UIImage *imageToDisplay =
    [[ImageStore defaultImageStore] imageForKey:imageKey];
    // Use that image to put on the screen in imageView
    [imageView setImage:imageToDisplay];
  } else {
    // Clear the imageView
    [imageView setImage:nil];
  }
}

 Dismissing the keyboard

When the keyboard appears on the screen in the possession detail view, it obscures imageView. This is annoying.

to dismiss the keyboard, conform to UITextFieldDelegate protocol

@interface ItemDetailViewController : UIViewController
<UINavigationControllerDelegate, UIImagePickerControllerDelegate,
UITextFieldDelegate>
//In ItemDetailViewController.m, implement textFieldShouldReturn:. - (BOOL)textFieldShouldReturn:(UITextField *)textField {   [textField resignFirstResponder];   return YES; }

UIControl

We have seen how classes like UIButton can send an action message to a target when tapped. Buttons
inherit this target-action behavior from their superclass, UIControl. You’re going to change the view
of ItemDetailViewController from an instance of UIView to an instance of UIControl so that it can
handle touch events.

select the main view instance. Open the identity inspector and change the view’s class to UIControl.

choose

Connection: Action

Event: Touch Up Inside

- (IBAction)backgroundTapped:(id)sender
{
  [[self view] endEditing:YES];
}

 

posted on 2012-06-16 17:35  grep  阅读(287)  评论(0编辑  收藏  举报