我有一个简单的应用程序,用户在其中签名,一旦完成,它会提示输入他们的名字。然后会出现另一个视图控制器,显示其名称和签名。
我可以让签名工作并显示,但是当我尝试将图像保存到核心数据时,我收到错误。
我已经阅读了将图片保存到coredata的帖子,但还没有成功。
#import "MyViewController.h"
@interface MyViewController ()
@end
@implementation MyViewController;UIImage (*mySignature);
@synthesize mySignatureImage;
@synthesize lastContactPoint1, lastContactPoint2, currentPoint;
@synthesize imageFrame;
@synthesize fingerMoved;
@synthesize navbarHeight;
@synthesize imageData;
@synthesize displaySignatureViewController;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
//set the title of the navigation view
[self.navigationItem setTitle:@"Sign here"];
//create a save button in the navigation bar
UIBarButtonItem *myButton = [[UIBarButtonItem alloc]
initWithTitle:@"Save"
style:UIBarButtonItemStylePlain
target:self
action:@selector(saveSignature:)];
[self.navigationItem setRightBarButtonItem:myButton];
//set the view background to light gray
self.view.backgroundColor = [UIColor lightGrayColor];
//get reference to the navigation frame to calculate navigation bar height
CGRect navigationframe = [[self.navigationController navigationBar] frame];
navbarHeight = navigationframe.size.height;
//create a frame for our signature capture based on whats remaining
imageFrame = CGRectMake(self.view.frame.origin.x+10,
self.view.frame.origin.y-5,
self.view.frame.size.width-20,
self.view.frame.size.height-navbarHeight-30);
//allocate an image view and add to the main view
mySignatureImage = [[UIImageView alloc] initWithImage:nil];
mySignatureImage.frame = imageFrame;
mySignatureImage.backgroundColor = [UIColor whiteColor];
[self.view addSubview:mySignatureImage];
}
//when one or more fingers touch down in a view or window
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
//did our finger moved yet?
fingerMoved = NO;
UITouch *touch = [touches anyObject];
//just clear the image if the user tapped twice on the screen
if ([touch tapCount] == 2) {
mySignatureImage.image = nil;
return;
}
//we need 3 points of contact to make our signature smooth using quadratic bezier curve
currentPoint = [touch locationInView:mySignatureImage];
lastContactPoint1 = [touch previousLocationInView:mySignatureImage];
lastContactPoint2 = [touch previousLocationInView:mySignatureImage];
}
//when one or more fingers associated with an event move within a view or window
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
//well its obvious that our finger moved on the screen
fingerMoved = YES;
UITouch *touch = [touches anyObject];
//save previous contact locations
lastContactPoint2 = lastContactPoint1;
lastContactPoint1 = [touch previousLocationInView:mySignatureImage];
//save current location
currentPoint = [touch locationInView:mySignatureImage];
//find mid points to be used for quadratic bezier curve
CGPoint midPoint1 = [self midPoint:lastContactPoint1 withPoint:lastContactPoint2];
CGPoint midPoint2 = [self midPoint:currentPoint withPoint:lastContactPoint1];
//create a bitmap-based graphics context and makes it the current context
UIGraphicsBeginImageContext(imageFrame.size);
//draw the entire image in the specified rectangle frame
[mySignatureImage.image drawInRect:CGRectMake(0, 0, imageFrame.size.width, imageFrame.size.height)];
//set line cap, width, stroke color and begin path
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 3.0f);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0.0, 0.0, 0.0, 1.0);
CGContextBeginPath(UIGraphicsGetCurrentContext());
//begin a new new subpath at this point
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), midPoint1.x, midPoint1.y);
//create quadratic Bézier curve from the current point using a control point and an end point
CGContextAddQuadCurveToPoint(UIGraphicsGetCurrentContext(),
lastContactPoint1.x, lastContactPoint1.y, midPoint2.x, midPoint2.y);
//set the miter limit for the joins of connected lines in a graphics context
CGContextSetMiterLimit(UIGraphicsGetCurrentContext(), 2.0);
//paint a line along the current path
CGContextStrokePath(UIGraphicsGetCurrentContext());
//set the image based on the contents of the current bitmap-based graphics context
mySignatureImage.image = UIGraphicsGetImageFromCurrentImageContext();
//remove the current bitmap-based graphics context from the top of the stack
UIGraphicsEndImageContext();
//lastContactPoint = currentPoint;
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
//just clear the image if the user tapped twice on the screen
if ([touch tapCount] == 2) {
mySignatureImage.image = nil;
return;
}
//if the finger never moved draw a point
if(!fingerMoved) {
UIGraphicsBeginImageContext(imageFrame.size);
[mySignatureImage.image drawInRect:CGRectMake(0, 0, imageFrame.size.width, imageFrame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 3.0f);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0.0, 0.0, 0.0, 1.0);
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
CGContextFlush(UIGraphicsGetCurrentContext());
mySignatureImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
}
//calculate midpoint between two points
- (CGPoint) midPoint:(CGPoint )p0 withPoint: (CGPoint) p1 {
return (CGPoint) {
(p0.x + p1.x) / 2.0,
(p0.y + p1.y) / 2.0
};
}
//save button was clicked, its time to save the signature
- (void) saveSignature:(id)sender {
//get reference to the button that requested the action
UIBarButtonItem *myButton = (UIBarButtonItem *)sender;
//check which button it is, if you have more than one button on the screen
//you must check before taking necessary action
if([myButton.title isEqualToString:@"Save"]){
NSLog(@"Clicked on the bar button");
//display an alert to capture the person's name
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Saving signature with name"
message:@"Please enter your name"
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"Ok", nil];
[alertView setAlertViewStyle:UIAlertViewStylePlainTextInput];
[alertView show];
}
}
//some action was taken on the alert view
- (void) alertView:(UIAlertView *)alertView
clickedButtonAtIndex:(NSInteger)buttonIndex{
//which button was pressed in the alert view
NSString *buttonTitle = [alertView buttonTitleAtIndex:buttonIndex];
//user wants to save the signature now
if ([buttonTitle isEqualToString:@"Ok"]){
NSLog(@"Ok button was pressed.");
NSLog(@"Name of the person is: %@", [[alertView textFieldAtIndex:0] text]);
NSString * personName = [[alertView textFieldAtIndex:0] text];
// //create path to where we want the image to be saved
// NSFileManager *fileManager = [NSFileManager defaultManager];
// NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
// NSString *documentsDirectory = [paths objectAtIndex:0];
// NSString *filePath = [documentsDirectory stringByAppendingPathComponent:@"MyFolder"];
//
// //if the folder doesn't exists then just create one
// NSError *error = nil;
// if (![[NSFileManager defaultManager] fileExistsAtPath:filePath])
// [[NSFileManager defaultManager] createDirectoryAtPath:filePath
// withIntermediateDirectories:NO
// attributes:nil
// error:&error];
//
// //convert image into .png format.
// NSData *imageData = UIImagePNGRepresentation(mySignatureImage.image);
// NSString *fileName = [filePath stringByAppendingPathComponent:
// [NSString stringWithFormat:@"%@.png", personName]];
//
// //creates an image file with the specified content and attributes at the given location
// [fileManager createFileAtPath:fileName contents:imageData attributes:nil];
// NSLog(@"image saved");
#pragma mark Core Data/ PNG Save
NSData *imageData = UIImagePNGRepresentation(mySignatureImage.image);
NSManagedObject *imageData = [[NSEntityDescription
insertNewObjectForEntityForName:@"imageData" inManagedObjectContext:self managedObjectContext] ]
//check if the display signature view controller doesn't exists then create it
if(self.displaySignatureViewController == nil){
DisplaySignatureViewController *displayView = [[DisplaySignatureViewController alloc] init];
self.displaySignatureViewController = displayView;
}
//pass the person's name to the next view controller
self.displaySignatureViewController.personName = personName;
//tell the navigation controller to push a new view into the stack
[self.navigationController pushViewController:self.displaySignatureViewController animated:YES];
}
//just forget it
else if ([buttonTitle isEqualToString:@"Cancel"]){
NSLog(@"Cancel button was pressed.");
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
答案 0 :(得分:2)
您在评论中提到您错误地抱怨"重新定义了具有不同类型的图像数据"。这是因为这两行:
NSData *imageData = UIImagePNGRepresentation(mySignatureImage.image);
NSManagedObject *imageData = [[NSEntityDescription
insertNewObjectForEntityForName:@"imageData"
inManagedObjectContext:self managedObjectContext] ]
您创建名为imageData
的变量。然后在下一行中创建另一个具有完全相同名称的变量。这在Objective-C中不是合法的语法,或者实际上是我见过的任何语言。这不是真正的核心数据问题,也不是图像处理问题,因为无论您尝试编写什么类型的代码,在重新声明类似的变量时都会遇到相同的错误。
您还没有使用这些变量中的任何一个,因此您将丢失图像。你可能想要