Tuesday, September 1, 2009
iPhone bits and bobs
- MapView code
A fully functional MapViewDelegate implementation for you. All you have to do to start putting items on maps is make them implement MKAnnotation, which is super-easy.
- (MKAnnotationView *)mapView:(MKMapView *)myMapView viewForAnnotation:(id)annotation {
//this is clumsy, but there's no obvious better way - otherwise it crashes when showing user location
if (![annotation isKindOfClass:[ECEntry class]])
return nil;
ECEntry *myEntry = (ECEntry*)annotation;
MKPinAnnotationView *myView = (MKPinAnnotationView*)[myMapView dequeueReusableAnnotationViewWithIdentifier:@"Local"];
if (myView==nil)
myView = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"Local"] autorelease];
myView.pinColor = myEntry.groupID==0 ? MKPinAnnotationColorGreen : MKPinAnnotationColorRed;
myView.canShowCallout=YES;
myView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
return myView;
}
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
ECEntryViewController *entryViewController = [[ECEntryViewController alloc] initWithNibName:nil bundle:nil];
entryViewController.myEntry = (ECEntry*)[view annotation];
[self.navigationController pushViewController:entryViewController animated:YES];
[entryViewController release];
} - Using the camera via UIImagePickerController
So this is amazingly easy, and I can even provide you with some code that
a) launches a camera, phot-album selector, or photo-library selector, depending on what's available on your device:
b) presents the image picker as a modal view controller, keeping it within your existing NavigationController tree:
c) gets the selected/captured image (via UIImagePickerControllerDelegate) and saves it to a file.
-(void) doCamera {
BOOL hasCamera = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera];
BOOL hasAlbum = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeSavedPhotosAlbum];
BOOL hasLibrary = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary];
if (hasCamera || hasAlbum || hasLibrary) {
UIImagePickerController *photoController = [[UIImagePickerController alloc] init];
photoController.delegate = self;
if (hasCamera)
photoController.sourceType = UIImagePickerControllerSourceTypeCamera;
else if (hasAlbum) {
photoController.sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
NSString *warningMessage = [NSString localizedStringWithFormat:@"Your device has no camera, but does have an album of saved photos to choose from"];
[Util doAlert:NSLocalizedString(@"Warning",@"Alert title") withMessage:warningMessage];
}
else if (hasLibrary) {
photoController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
NSString *warningMessage = [NSString localizedStringWithFormat:@"Your device has no camera, but does have a photo library to choose from"];
[Util doAlert:NSLocalizedString(@"Warning",@"Alert title") withMessage:warningMessage];
}
[self doSave];
[self presentModalViewController:photoController animated:YES];
[photoController release];
}
else {
NSString *alertMessage = [NSString localizedStringWithFormat:@"Your device does not support photos"];
[Util doAlert:NSLocalizedString(@"No photo support",@"Alert title") withMessage:alertMessage];
}
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage];
if (image == nil)
image = [info objectForKey:UIImagePickerControllerOriginalImage];
//TODO, if possible: if the image has already been saved, just use its path, don't save it again
if (image!=nil) {
//convert image to NSData - use Settings for PNG/JPG
[Util showActivity];
NSData *imageData=nil;
if ([Settings saveImagesAsPNG])
imageData = [NSData dataWithData:UIImagePNGRepresentation(image)];
else
imageData = [NSData dataWithData:UIImageJPEGRepresentation(image, [Settings getJPEGQuality])];
//save NSData to file
NSString *pathDir = [Util getApplicationDocumentsPath];
NSString *fileName = [[NSProcessInfo processInfo] globallyUniqueString];
fileName = [fileName stringByAppendingString:([Settings saveImagesAsPNG] ? @".png" : @".jpg")];
NSString *fullPath = [pathDir stringByAppendingPathComponent:fileName];
NSError *error=nil;
[imageData writeToFile:fullPath options:NSAtomicWrite error:&error];
if (error) {
NSString *errorMessage = [NSString localizedStringWithFormat:@"Unable to write to file %@: %@ - %@", fullPath, error, [error userInfo]];
[Util doAlert:NSLocalizedString(@"Error",@"Alert title") withMessage:errorMessage];
}
[Util stopShowingActivity];
//set entry
myEntry.photoPath=fileName;
//all done
[self dismissModalViewControllerAnimated:YES];
[self.tableView reloadData];
}
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[self dismissModalViewControllerAnimated:YES];
[self.tableView reloadData];
} - Unit test woes
I've been having loads of trouble with the allegedly-baked-in unit-testing framework described here. Specifically, I get masses of "symbol(s) not found" linker errors when I try to compile for the Testing target, re all kinds of basic UIKit and CoreData stuff. I presume it's some kind of importing-the-wrong-kind-of-framework problem, but I have no idea how to correct it, and I don't want to dive into the seething nest of rattlesnakes that is the innards of XCode's build process. Should I just switch to the Google unit-test framework for iPhone?
Labels: ImagePicker, iPhone, MapView, MKAnnotation, MKMapView, presentModalViewController, SenTestingKit, UIImagePIckerController, UIImagePickerControllerDelegate
Subscribe to Posts [Atom]