简单来说,我的问题是:一些加载到某些网页视图中的PDF文件没有显示出来,而另一些则显示,如下图所示(请注意我编辑的图片放置了假的pdf内容,原文无法发布)。
第二个UIWebView高度是正确的,来自PDF高度,但其内容未呈现
我的应用必须在一系列网页浏览中显示非常短的PDF(假设这是强制性要求,我无法切换到其他任何内容。这些PDF是LaTex生成的,包含无法显示到UILabel的文本等等此外,它们长约4-5行)。
布局如下:有一个垂直滚动视图,它有一个视图(内容视图)作为直接子视图。单个UIWebView
(黄色背景)嵌入在继承自UIView
(PDFView
,蓝色背景)的自定义类中,因此我可以将该类指定为webview的委托并执行webview初始化+约束设置只在一个地方。 webview userInteraction
已停用。在内容视图中,我为每个PDF动态添加一个PDFView
,设置约束并调用loadData:MIMEType:textEncodingName:baseURL:
从磁盘上的文件加载PDF(来自NSData
,白框)。由于PDFView
是其UIWebView
的委托,因此当它完成加载其内容(pdf)时,我会更改webview高度约束以匹配webview.scrollview.contentsize.height
。这允许我调整webview的大小,以便显示整个PDF。 Autolayout负责设置scrollview contentsize.height
,以便用户可以滚动整个pdf列表。
一切似乎都运行正常但有时候,在某些网页浏览中,内容不会呈现。当webViewDidFinishLoad:
的调用触发时,webView.scrollView.contentSize.height
值是正确的(实际上,webview具有正确的高度),并且在autolayout完成其工作之后,webview的内容尚未呈现的框架具有正确的尺寸。这让我认为它必定是某种渲染问题,因为它似乎是在不同的webview和不同的pdf上随机发生的。有时我必须在出现问题之前手动按下并弹出控制器10次,有时它会出现在第一次按下时。内存消耗似乎很好,并且没有任何内存警告。
我检查了每个数据并查看:没有人是零。此外,永远不会调用委托webView:didFailLoadWithError:
,因此webview始终会成功加载其内容(每次调用webViewDidFinishLoad:
,即使对于不显示任何内容的Web视图也是如此。 PDF数据很好,因为我将其加载到内存中,再次保存在另一个pdf文件中并使用PDF查看器打开。我不是使用故事板而是使用xib。我的目标是iOS 7 +。
代码如下:
PDFView.h
@interface PDFView : UIView
-(instancetype) initWithData:(NSData *)pdfData at:(NSInteger)position;
@end
PDFView.m
#import "PDFView.h"
@interface PDFView() <UIWebViewDelegate>
@property (strong, nonatomic) UIWebView * contentUIWV;
@property (strong, nonatomic) NSLayoutConstraint * contentHeightNSLC;
@end
@implementation PDFView
-(instancetype) initWithData:(NSData *)pdfData at:(NSInteger)position
{
self = [super init];
if (self)
{
[self initViews];
[self setConstraints];
[self fillViews:pdfData];
self.tag = position;
}
return self;
}
-(void) initViews
{
_contentUIWV = [[UIWebView alloc] init];
[_contentUIWV setContentHuggingPriority:250 forAxis:UILayoutConstraintAxisVertical];
_contentUIWV.userInteractionEnabled = NO;
_contentUIWV.delegate = self;
_contentUIWV.scalesPageToFit = YES;
_contentUIWV.backgroundColor = [UIColor yellowColor];
[self addSubview:_contentUIWV];
}
-(void) setConstraints
{
_contentUIWV.translatesAutoresizingMaskIntoConstraints = NO;
NSDictionary * viewsNSD = @{ @"contentUIWV":_contentUIWV };
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-8-[contentUIWV]-8-|" options:0 metrics:nil views:viewsNSD]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-8-[contentUIWV]-8-|" options:0 metrics:nil views:viewsNSD]];
NSArray * constraintsNSA = [NSLayoutConstraint constraintsWithVisualFormat:@"V:[contentUIWV(==1)]" options:0 metrics:nil views:viewsNSD];
self.contentHeightNSLC = constraintsNSA.firstObject;
[self.contentUIWV addConstraints:constraintsNSA];
}
-(void) fillViews:(NSData *)pdfData
{
#ifdef DEBUG
NSLog(@"PDFView::fillViews: %ld %@", (long)self.tag, pdfData?@"NOT null":@"NULL");
#endif
[_contentUIWV loadData:pdfData MIMEType:@"application/pdf" textEncodingName:@"utf-8" baseURL:nil];
}
#pragma mark - UIWebViewDelegate
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
return YES;
}
-(void) webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
#ifdef DEBUG
NSLog(@"PDFView::webView:didFailLoadWithError: %@", error.localizedDescription);
#endif
}
-(void) webViewDidFinishLoad:(UIWebView *)webView
{
#ifdef DEBUG
NSLog(@"PDFView::webViewDidFinishLoad: %ld new height (%ld)", (long)self.tag, (long)webView.scrollView.contentSize.height);
#endif
self.contentHeightNSLC.constant = webView.scrollView.contentSize.height;
}
@end
Controller.m或者
#import "Controller.h"
#import "PDFView.h"
@interface Controller ()
// This Mutable Array stores the NSData of each PDF (PDF are loaded form disk and stored as NSData)
@property (strong, nonatomic) NSMutableArray * exerciseDataNSMA;
@property (weak, nonatomic) IBOutlet UIView *mainUIV;
@property (weak, nonatomic) IBOutlet UIScrollView *scrollUISV;
@property (weak, nonatomic) IBOutlet UIView *contentUIV;
@end
@implementation Controller
- (void)viewDidLoad
{
[super viewDidLoad];
// ... omitted code inits self.exerciseDataNSMA and stores pdf content in it
[self loadContentView];
}
#pragma mark - Private Methods
-(void) loadContentView
{
// Subviews by name (used for constraint bindings)
NSMutableDictionary * subviews = [[NSMutableDictionary alloc] init];
// String in Visual Language Format to create vertical scrollview's contentview constraint
NSMutableString *strVerticalConstraint = [[NSMutableString alloc] initWithString:@"V:|"];
for (NSInteger i=0; i<self.exerciseDataNSMA.count; i++)
{
PDFView * pdfView = [[PDFView alloc] initWithData:self.exerciseDataNSMA[i] at:i];
pdfView.delegate = self;
pdfView.backgroundColor = [UIColor blueColor];
pdfView.translatesAutoresizingMaskIntoConstraints = NO;
[self.contentUIV addSubview:pdfView];
[self.contentUIV addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[pdfView]|" options:0 metrics:nil views:@{@"pdfView":pdfView}]];
NSString * exerciseUIVName = [NSString stringWithFormat:@"pdfView%ld", (long)i];
[strVerticalConstraint appendString:[NSString stringWithFormat:@"[%@]-8-", exerciseUIVName]];
subviews[exerciseUIVName] = pdfView;
}
[strVerticalConstraint appendString:@"|"];
// Add content view constraints
[self.contentUIV addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:strVerticalConstraint options:0 metrics:nil views:subviews]];
}
@end
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Without the cache disabled, the webviews do not resize their height
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"WebKitDiskImageCacheEnabled"];
[[NSUserDefaults standardUserDefaults] synchronize];
// ... unrelated stuff
return YES;
}
Controller上的约束如下:
请注意,在运行时删除了高度约束。
知道为什么会这样吗?关于如何解决它的任何想法?
这是我已经尝试过的:
loadContentView
而不将pdfData加载到webview中。控制器出现后,将pdfData加载到webviews; loadData:MIMEType:textEncodingName:baseURL:
,等待webViewDidFinishLoad:
,然后为第二个webview重复此序列,依此类推;