我目前正在使用 CALayer
和 renderInContext
方法从 iOS 中的 UIView 创建 PDF 文档。
我面临的问题是标签的清晰度。我创建了一个 UILabel
子类,它重写 drawLayer
,如下所示:
/** Overriding this CALayer delegate method is the magic that allows us to draw a vector version of the label into the layer instead of the default unscalable ugly bitmap */
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
BOOL isPDF = !CGRectIsEmpty(UIGraphicsGetPDFContextBounds());
if (!layer.shouldRasterize && isPDF)
[self drawRect:self.bounds]; // draw unrasterized
else
[super drawLayer:layer inContext:ctx];
}
此方法可以让我绘制漂亮清晰的文本,但是问题在于我无法控制的其他 View 。有没有任何方法可以让我对 UITableView
或 UIButton
中嵌入的标签执行类似的操作。我想我正在寻找一种方法来迭代 View 堆栈并做一些事情来让我绘制更清晰的文本。
这是一个例子: 该文本渲染得很好(我的自定义 UILabel 子类)
标准分段控件中的文本不那么清晰:
编辑:我正在获取要绘制到 PDF 中的上下文,如下所示:
UIGraphicsBeginPDFContextToData(self.pdfData, CGRectZero, nil);
pdfContext = UIGraphicsGetCurrentContext();
UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, 612, 792), nil);
[view.layer renderInContext:pdfContext];
最佳答案
我最终遍历了 View 层次结构并将每个 UILabel
设置为覆盖 drawLayer
的自定义子类。
这是我遍历 View 的方法:
+(void) dumpView:(UIView*) aView indent:(NSString*) indent {
if (aView) {
NSLog(@"%@%@", indent, aView); // dump this view
if ([aView isKindOfClass:[UILabel class]])
[AFGPDFDocument setClassForLabel:aView];
if (aView.subviews.count > 0) {
NSString* subIndent = [[NSString alloc] initWithFormat:@"%@%@",
indent, ([indent length]/2)%2==0 ? @"| " : @": "];
for (UIView* aSubview in aView.subviews)
[AFGPDFDocument dumpView:aSubview indent:subIndent];
}
}
}
以及我如何更改类(class):
+(void) setClassForLabel: (UIView*) label {
static Class myFancyObjectClass;
myFancyObjectClass = objc_getClass("UIPDFLabel");
object_setClass(label, myFancyObjectClass);
}
比较:
旧:
新:
不确定是否有更好的方法来做到这一点,但它似乎适合我的目的。
编辑:找到了一种更通用的方法来执行此操作,该方法不涉及更改类或遍历整个 View 层次结构。我正在使用方法调配。如果需要,此方法还可以让您做一些很酷的事情,例如用边框包围每个 View 。首先,我使用 drawLayer
方法的自定义实现创建了一个类别 UIView+PDF
,然后在 load
方法中使用以下内容:
// The "+ load" method is called once, very early in the application life-cycle.
// It's called even before the "main" function is called. Beware: there's no
// autorelease pool at this point, so avoid Objective-C calls.
Method original, swizzle;
// Get the "- (void) drawLayer:inContext:" method.
original = class_getInstanceMethod(self, @selector(drawLayer:inContext:));
// Get the "- (void)swizzled_drawLayer:inContext:" method.
swizzle = class_getInstanceMethod(self, @selector(swizzled_drawLayer:inContext:));
// Swap their implementations.
method_exchangeImplementations(original, swizzle);
根据此处的示例进行操作:http://darkdust.net/writings/objective-c/method-swizzling
关于iOS 从 UIView 创建 PDF,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12850684/