2

我目前正在使用CALayerandrenderInContext方法从 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];
}

这种方法可以让我画出漂亮清晰的文本,但是,问题在于我无法控制的其他视图。有没有什么方法可以让我对嵌入的标签做类似的事情UITableViewor UIButton。我想我正在寻找一种方法来遍历视图堆栈并做一些事情来让我绘制更清晰的文本。

这是一个示例:此文本呈现得很好(我的自定义 UILabel 子类) 伊姆古尔

标准分段控件中的文本没有那么清晰:

伊姆古尔

编辑:我正在获取要绘制到我的 PDF 中的上下文,如下所示:

UIGraphicsBeginPDFContextToData(self.pdfData, CGRectZero, nil);
pdfContext = UIGraphicsGetCurrentContext();
UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, 612, 792), nil);
[view.layer renderInContext:pdfContext];
4

1 回答 1

2

我最终遍历了视图层次结构并将 each 设置UILabel为我的自定义子类覆盖drawLayer.

这是我遍历视图的方式:

+(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];
        }
    }
}

以及我如何更改课程:

+(void) setClassForLabel: (UIView*) label {
    static Class myFancyObjectClass;
    myFancyObjectClass = objc_getClass("UIPDFLabel");
    object_setClass(label, myFancyObjectClass);
}

比较:

老的:

图片

新的:

伊姆古尔

不确定是否有更好的方法来做到这一点,但它似乎对我的目的有用。

编辑:找到了一种更通用的方法来做到这一点,它不涉及更改类或遍历整个视图层次结构。我正在使用方法调配。这种方法还可以让你做一些很酷的事情,比如如果你愿意,可以用边框包围每个视图。UIView+PDF首先,我使用该方法的自定义实现创建了一个类别drawLayer,然后在该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

于 2012-10-12T01:58:03.383 回答