签名捕获IOS

时间:2014-07-23 09:18:35

标签: ios xcode core-data uiimage nsdictionary

我有一个简单的应用程序,用户在其中签名,一旦完成,它会提示输入他们的名字。然后会出现另一个视图控制器,显示其名称和签名。

我可以让签名工作并显示,但是当我尝试将图像保存到核心数据时,我收到错误。

我已经阅读了将图片保存到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

1 个答案:

答案 0 :(得分:2)

您在评论中提到您错误地抱怨"重新定义了具有不同类型的图像数据"。这是因为这两行:

NSData *imageData = UIImagePNGRepresentation(mySignatureImage.image);


NSManagedObject *imageData =  [[NSEntityDescription
                                insertNewObjectForEntityForName:@"imageData"
                                inManagedObjectContext:self managedObjectContext] ]

您创建名为imageData的变量。然后在下一行中创建另一个具有完全相同名称的变量。这在Objective-C中不是合法的语法,或者实际上是我见过的任何语言。这不是真正的核心数据问题,也不是图像处理问题,因为无论您尝试编写什么类型的代码,在重新声明类似的变量时都会遇到相同的错误。

您还没有使用这些变量中的任何一个,因此您将丢失图像。你可能想要

  • 将PNG纳入一个变量
  • 不同的变量中创建托管对象,并将图像指定为其属性之一
  • 保存对托管对象上下文的更改。