在 iOS 中将子视图图像打印为 PDF

发布于 2024-11-07 15:35:31 字数 4440 浏览 0 评论 0原文

我试图从 iPad 的触摸屏上获取指纹签名,将其打印为 PDF,然后将生成的 PDF 通过电子邮件发送到预设地址。我编写了一个 UIView 子类,它在当前拖动事件的位置到最后一个拖动事件的位置之间添加了线条,如下所示。我在实现电子邮件部分时没有遇到任何麻烦。子类的声明:

#import <UIKit/UIKit.h>

@interface SignatureView : UIView {
    UIImageView *drawImage;
    @public
    UIImage *cachedSignature;
}
@property (nonatomic, retain) UIImage* cachedSignature;
-(void) clearView;

@end

和实现:

#import "SignatureView.h"

@implementation SignatureView

Boolean drawSignature=FALSE;
float oldTouchX=-1;
float oldTouchY=-1;
float nowTouchX=-1;
float nowTouchY=-1;
@synthesize cachedSignature;
//UIImage *cachedSignature=nil;

- (id)initWithFrame:(CGRect)frame {

    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code.
    }
    return self;
    if (cachedSignature==nil){
        if(UIGraphicsBeginImageContextWithOptions!=NULL){
            UIGraphicsBeginImageContextWithOptions(self.frame.size, NO, 0.0);
        }else{
            UIGraphicsBeginImageContext(self.frame.size);
        }
        [self.layer renderInContext:UIGraphicsGetCurrentContext()];
        cachedSignature = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    }
}

- (void)drawRect:(CGRect)rect {
    //get image of current state of signature field
    [self.layer renderInContext:UIGraphicsGetCurrentContext()];
    cachedSignature = UIGraphicsGetImageFromCurrentImageContext();

    //draw cached signature onto signature field, no matter what.

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextDrawImage(context, CGRectMake(0,0,302,90),cachedSignature.CGImage);

    if(oldTouchX>0 && oldTouchY>0 && nowTouchX>0 && nowTouchY>0){
        CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
        CGContextSetLineWidth(context, 2);
                //make change to signature field
        CGContextMoveToPoint(context, oldTouchX, oldTouchY);

        CGContextAddLineToPoint(context, nowTouchX, nowTouchY);
        CGContextStrokePath(context);
    }
 }
-(void) clearView{
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetGrayFillColor(context, 0.75, 1.0);
    CGContextFillRect(context, CGRectMake(0,0,800,600));
    CGContextFlush(context);
    cachedSignature = UIGraphicsGetImageFromCurrentImageContext();
    [self setNeedsDisplay];
}

-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    CGPoint location=[[touches anyObject] locationInView:self];
    oldTouchX=nowTouchX;
    oldTouchY=nowTouchY;
    nowTouchX=location.x;
    nowTouchY=location.y;
    [self setNeedsDisplay];
}
-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    CGPoint location=[[touches anyObject] locationInView:self];
    oldTouchX=nowTouchX;
    oldTouchY=nowTouchY;
    nowTouchX=location.x;
    nowTouchY=location.y;
    [self setNeedsDisplay];
}

 -(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
     oldTouchX=-1;
     oldTouchY=-1;
     nowTouchX=-1;
     nowTouchY=-1;
 }

- (void)dealloc {
    [super dealloc];
}


@end

但是,我在将签名打印到 PDF 时遇到问题。据我了解上面的代码,它应该在最后一次移动之前将签名的副本保留为名为cachedSignature的UIImage,可供所有人访问。但是,当我尝试使用以下内容将其写入 PDF 上下文时:

    UIGraphicsBeginPDFContextToFile(fileName, CGRectZero, nil);
    UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, 612, 792), nil);
    UIImage* background=[[UIImage alloc] initWithContentsOfFile:backgroundPath];
    // Create the PDF context using the default page size of 612 x 792.
    // Mark the beginning of a new page.
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(context, 0.0, 792);
    CGContextScaleCTM(context, 1.0, -1.0);
    //CGContextDrawImage(context, CGRectMake(0,0,612,790),background.CGImage);
    //draw signature images
    UIImage *y=clientSignatureView.cachedSignature;
    CGContextDrawImage(context, CGRectMake(450, 653, 600, 75), y.CGImage);
    //CGContextDrawImage(context, CGRectMake(75, 75, 300, 300),     techSignatureView.cachedSignature.CGImage);
    CGContextTranslateCTM(context, 0.0, 792);
    CGContextScaleCTM(context, 1.0, -1.0);

它失败了。在此实例中,“techSignatureView”和“clientSignatureView”是上面定义的自定义 UIView 的实例,连接到运行此代码的同一父 UIView 中的插座。

我不知道出了什么问题。我已经取消了打印背景图像的调用,以防它们被打印在它的“后面”,但没有结果。使用调试器检查上面代码中的“y”,发现它有 nil 协议条目和 nil 方法条目;所以我怀疑它没有被正确访问 - 除此之外,我一无所知,不知道如何继续。

I am attempting to take a fingerpainted signature from the iPad's touch screen, print it to PDF, and then email the resulting PDF to a preset address. I have a UIView subclass written that adds lines between the current drag event's location to the last drag event's location, as shown below. I have had no troubles implementing the emailing portion. The subclass's declaration:

#import <UIKit/UIKit.h>

@interface SignatureView : UIView {
    UIImageView *drawImage;
    @public
    UIImage *cachedSignature;
}
@property (nonatomic, retain) UIImage* cachedSignature;
-(void) clearView;

@end

And implementation:

#import "SignatureView.h"

@implementation SignatureView

Boolean drawSignature=FALSE;
float oldTouchX=-1;
float oldTouchY=-1;
float nowTouchX=-1;
float nowTouchY=-1;
@synthesize cachedSignature;
//UIImage *cachedSignature=nil;

- (id)initWithFrame:(CGRect)frame {

    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code.
    }
    return self;
    if (cachedSignature==nil){
        if(UIGraphicsBeginImageContextWithOptions!=NULL){
            UIGraphicsBeginImageContextWithOptions(self.frame.size, NO, 0.0);
        }else{
            UIGraphicsBeginImageContext(self.frame.size);
        }
        [self.layer renderInContext:UIGraphicsGetCurrentContext()];
        cachedSignature = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    }
}

- (void)drawRect:(CGRect)rect {
    //get image of current state of signature field
    [self.layer renderInContext:UIGraphicsGetCurrentContext()];
    cachedSignature = UIGraphicsGetImageFromCurrentImageContext();

    //draw cached signature onto signature field, no matter what.

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextDrawImage(context, CGRectMake(0,0,302,90),cachedSignature.CGImage);

    if(oldTouchX>0 && oldTouchY>0 && nowTouchX>0 && nowTouchY>0){
        CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
        CGContextSetLineWidth(context, 2);
                //make change to signature field
        CGContextMoveToPoint(context, oldTouchX, oldTouchY);

        CGContextAddLineToPoint(context, nowTouchX, nowTouchY);
        CGContextStrokePath(context);
    }
 }
-(void) clearView{
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetGrayFillColor(context, 0.75, 1.0);
    CGContextFillRect(context, CGRectMake(0,0,800,600));
    CGContextFlush(context);
    cachedSignature = UIGraphicsGetImageFromCurrentImageContext();
    [self setNeedsDisplay];
}

-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    CGPoint location=[[touches anyObject] locationInView:self];
    oldTouchX=nowTouchX;
    oldTouchY=nowTouchY;
    nowTouchX=location.x;
    nowTouchY=location.y;
    [self setNeedsDisplay];
}
-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    CGPoint location=[[touches anyObject] locationInView:self];
    oldTouchX=nowTouchX;
    oldTouchY=nowTouchY;
    nowTouchX=location.x;
    nowTouchY=location.y;
    [self setNeedsDisplay];
}

 -(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
     oldTouchX=-1;
     oldTouchY=-1;
     nowTouchX=-1;
     nowTouchY=-1;
 }

- (void)dealloc {
    [super dealloc];
}


@end

I am, however, having trouble printing the signature to a PDF. As I understand the above code, it should keep a copy of the signature before the last move was made as a UIImage named cachedSignature, accessible to all. However, when I try to write it to a PDF context with the following:

    UIGraphicsBeginPDFContextToFile(fileName, CGRectZero, nil);
    UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, 612, 792), nil);
    UIImage* background=[[UIImage alloc] initWithContentsOfFile:backgroundPath];
    // Create the PDF context using the default page size of 612 x 792.
    // Mark the beginning of a new page.
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(context, 0.0, 792);
    CGContextScaleCTM(context, 1.0, -1.0);
    //CGContextDrawImage(context, CGRectMake(0,0,612,790),background.CGImage);
    //draw signature images
    UIImage *y=clientSignatureView.cachedSignature;
    CGContextDrawImage(context, CGRectMake(450, 653, 600, 75), y.CGImage);
    //CGContextDrawImage(context, CGRectMake(75, 75, 300, 300),     techSignatureView.cachedSignature.CGImage);
    CGContextTranslateCTM(context, 0.0, 792);
    CGContextScaleCTM(context, 1.0, -1.0);

It fails. In this instance 'techSignatureView' and 'clientSignatureView' are instances of the custom UIView as defined above, connected to outlets in the same parent UIView as is running this code.

I don't know what's going wrong. I've taken out the call to print the background image, in case they were being printed 'behind' it, with no results. Using the debugger to inspect 'y' in the above code reveals that it has nil protocol entries and nil method entries; so I suspect it's not being accessed properly - beyond that, I'm clueless and don't know how to proceed.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

游魂 2024-11-14 15:35:31

首先,当您尝试绘制它时,您的cachedSignature可能不再存在,因为它是自动释放的。分配时请使用属性设置器,因此不要使用 cachedSignature = foo 编写 self.cachedSignature = foo

另外,UIGraphicsGetImageFromCurrentImageContext 仅适用于图像上下文,您不能在 drawRect: 中将其与当前上下文一起使用。 drawRect: 方法负责将视图绘制到屏幕上,您无法从同一上下文创建图像,必须使用 UIGraphicsBeginImageContext 创建一个新的上下文将图像绘制到。无论如何,drawRect: 方法并不是最好的地方,因为如果每次触摸移动时都渲染图像,性能可能会很差。相反,我建议在 touchesEnded:withEvent: 实现中渲染图像的签名。

First of all, your cachedSignature probably doesn't exist anymore when you try to draw it, because it's autoreleased. Use the property setter when you assign it, so instead of cachedSignature = foo write self.cachedSignature = foo.

Also, UIGraphicsGetImageFromCurrentImageContext only works for image contexts, you cannot use this in drawRect: with the current context. The drawRect: method takes care of drawing your view to the screen, you cannot create an image from the same context, you have to use UIGraphicsBeginImageContext to create a new context that you draw the image into. The drawRect: method is not the best place for that anyway, because performance will likely be bad if you render the image every time a touch moves. Instead, I'd suggest to render the signature to the image in your touchesEnded:withEvent: implementation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文