2

iOS アプリで動的に PDF ドキュメントを作成しています。HTML 形式の文字列を NSAttributedString に変換してから、PDF ドキュメント ページに配置しようとしています。

文字列をプレーンな NSString として扱うと、そのフレームを設定して、ページ上の任意の場所に配置できます (文字列に含まれる html タグ)。

initWithString を使用して NSAttributedString を作成すると、結果の属性付き文字列をページのどこにでも配置できます。

を使用して文字列を NSAttributedString に変換すると

NSAttributedString initWithData:options:documentAttributes:error:

変換は完全に機能し、タグは属性に変換されます。しかし、文字列のフレームをページ上に配置しようとすると、フレームを 0,0 から上下に移動すると、テキストが切り取られます。テキストが行ごとに上部から切り取られる前に、フレームを 20 ポイント下に移動できます。すべてのテキストがページから消えると、原点が幅よりも大きくなるまでフレームを右に移動できます。

コード:

#pragma mark - === PDF BUILD Methods === -

- (void)buildPDF {

self.pdfPageSize = CGSizeMake(850.0, 1100.0);
UIFont *titleFont = [UIFont fontWithName:@"Dispatch-Bold" size:24.0];
UIFont *bodyFont = [UIFont systemFontOfSize:18.0];

// Open a new PDF dcument
[self setupPDFDocumentNamed:@"testPDF" Width:self.pdfPageSize.width Height:self.pdfPageSize.height];

//cover page
[self beginPDFPage];

NSString *title = [NSString stringWithFormat:@"How to Tie a %@", self.knot.knotName];
[self addText:title withFrame:CGRectMake(0, 10, 850, 30) font:titleFont alignment:NSTextAlignmentCenter];

[self addLineWithFrame:CGRectMake(10, 40, 830, 2) withColor:[CSCColors favoritesColor]];

NSString *imageName = [NSString stringWithFormat:@"%@_0", self.knot.knotID];
[self addImage:[UIImage imageNamed:imageName] atPoint:CGPointMake(50, 50)];

// addText method works, but addHTML method does not
//[self addText:self.knot.knotDescription withFrame:CGRectMake(400, 50, 300, 500) font:bodyFont alignment:NSTextAlignmentLeft];
[self addHTMLText:self.knot.knotDescription withFrame:CGRectMake(400, 50, 300, 500) font:bodyFont alignment:NSTextAlignmentLeft];

//close out the PDF
[self finishPDF];

}

-(void)setupPDFDocumentNamed:(NSString*)name Width:(float)width Height:(float)height {
self.pdfPageSize = CGSizeMake(width, height);

NSString *newPDFName = [NSString stringWithFormat:@"%@.pdf", name];

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];

NSString *pdfPath = [documentsDirectory stringByAppendingPathComponent:newPDFName];

UIGraphicsBeginPDFContextToFile(pdfPath, CGRectZero, nil);
}

- (void)beginPDFPage {
UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, self.pdfPageSize.width, self.pdfPageSize.height), nil);
}

- (void)finishPDF {
UIGraphicsEndPDFContext();
}

- (void)addText:(NSString*)text withFrame:(CGRect)frame font:(UIFont*)font alignment:(NSTextAlignment)alignment{

// Set up character and paragraph attributes
UIColor * cscBlueColor = [UIColor colorWithRed:0.0 green:0.53 blue:0.8 alpha:1.0];

NSMutableParagraphStyle *paraStyle = [[NSMutableParagraphStyle alloc] init];
paraStyle.lineBreakMode = NSLineBreakByWordWrapping;
paraStyle.alignment = alignment;

//Calculate frame
NSDictionary *attr = @{NSFontAttributeName:font};

CGRect textRect = [text boundingRectWithSize:frame.size options:NSStringDrawingUsesLineFragmentOrigin attributes:attr context:nil];

CGSize stringSize = textRect.size;

float textWidth = frame.size.width;

if (textWidth < stringSize.width)
    textWidth = stringSize.width;
if (textWidth > _pdfPageSize.width)
    textWidth = _pdfPageSize.width - frame.origin.x;

CGRect renderingRect = CGRectMake(frame.origin.x, frame.origin.y, textWidth, stringSize.height);

NSDictionary *renderingAttr = @{NSParagraphStyleAttributeName:paraStyle, NSFontAttributeName:font, NSForegroundColorAttributeName:cscBlueColor};
[text drawInRect:renderingRect withAttributes:renderingAttr];

}

- (void)addHTMLText:(NSString*)text withFrame:(CGRect)frame font:(UIFont *)font alignment:(NSTextAlignment)alignment{

NSMutableAttributedString *myString = [[NSMutableAttributedString alloc] initWithData:[text dataUsingEncoding:NSUTF8StringEncoding]
                                                                              options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
                                                                          NSCharacterEncodingDocumentAttribute: [NSNumber numberWithInt:NSUTF8StringEncoding]}
                                                                   documentAttributes:nil
                                                                                error:nil];
NSRange myRange;
myRange.location = 0;
myRange.length = myString.length;

// Set up character and paragraph attributes
UIColor * cscBlueColor = [UIColor colorWithRed:0.0 green:0.53 blue:0.8 alpha:1.0];

NSMutableParagraphStyle *paraStyle = [[NSMutableParagraphStyle alloc] init];
paraStyle.lineBreakMode = NSLineBreakByWordWrapping;
paraStyle.paragraphSpacing = 10.0f;
paraStyle.alignment = alignment;

NSDictionary *renderingAttr = @{NSParagraphStyleAttributeName:paraStyle, NSFontAttributeName:font, NSForegroundColorAttributeName:cscBlueColor};
[myString addAttributes:renderingAttr range:myRange];


//Calculate frame
NSStringDrawingContext *sdctx = [[NSStringDrawingContext alloc] init];
CGRect textRect = [myString boundingRectWithSize:CGSizeMake(frame.size.width, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin context:sdctx];

CGSize stringSize = textRect.size;

float textWidth = frame.size.width;

if (textWidth < stringSize.width)
    textWidth = stringSize.width;
if (textWidth > _pdfPageSize.width)
    textWidth = _pdfPageSize.width - frame.origin.x;

CGRect renderingRect = CGRectMake(frame.origin.x, frame.origin.y, textWidth, stringSize.height);

// fill rect so we can visualize the frame
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [UIColor lightGrayColor].CGColor);
CGContextFillRect(context, renderingRect);

//[myString drawInRect:renderingRect];
[myString drawWithRect:renderingRect options:NSStringDrawingUsesLineFragmentOrigin context:sdctx];

}


- (void)addImage:(UIImage*)image atPoint:(CGPoint)point {
CGRect imageFrame = CGRectMake(point.x, point.y, image.size.width, image.size.height);
[image drawInRect:imageFrame];
}

- (void)addLineWithFrame:(CGRect)frame withColor:(UIColor*)color {
CGContextRef currentContext = UIGraphicsGetCurrentContext();

CGContextSetStrokeColorWithColor(currentContext, color.CGColor);

// this is the thickness of the line
CGContextSetLineWidth(currentContext, 2);

CGPoint startPoint = frame.origin;
CGPoint endPoint = CGPointMake(frame.origin.x + frame.size.width, frame.origin.y);

CGContextBeginPath(currentContext);
CGContextMoveToPoint(currentContext, startPoint.x, startPoint.y);
CGContextAddLineToPoint(currentContext, endPoint.x, endPoint.y);

CGContextClosePath(currentContext);
CGContextDrawPath(currentContext, kCGPathFillStroke);

}

何か案は?

画面キャプチャ:

最初の 2 つのスクリーン キャップには、

NSAttributedString initWithData:options:documentAttributes:error:

属性付き文字列を生成する

最初の例では、フレームが {400, 50, 300, 500} に設定され、テキストが完全に切り取られています。

2 番目のフレームは {400, 50, 401, 500} で、テキストが表示されますが、最初の 2 行のテキストが上部でクリップされます。フレームを 20 まで移動すると、すべての線が表示されます。

最後のスクリーン ショットでは、属性付きの文字列を取得するために initWithString を使用しました。HTML が属性に変換されないことを除いて、すべてが正常に機能します。

灰色のボックスはテキストのフレームです ここに画像の説明を入力 ここに画像の説明を入力

また、HTML 文字列をクリーンアップして、タグとクラス呼び出しが奇妙な属性を導入していないことを確認しました。クリーンアップされた文字列の結果は同じです。

<html><body><p>Landlubbers need not apply. The Sheet Bend is an essential knot to know and one of the first knots taught to new sailors. It is very fast to tie and is useful when joining two ropes of different diameters.</p><p>Also known as Becket bend (when made fast to an eye instead of a loop), the Sheet Bend is often considered one of the most essential knots and is related in structure to the bowline. If the two free ends are not on the same side of the knot, the result is a left-handed sheet bend of significantly reduced strength.</p></body></html>

ありがとう

4

0 に答える 0