Ios UIWebView内容有时不呈现
简而言之,我的问题是:加载到某些web视图中的某些pdf不会显示,而其他pdf会显示,如下图所示(请注意,我编辑的图像中放置了伪造的pdf内容,原始内容无法发布) 三个PDF已正确加载到三个UIWebView中 第二个UIWebView高度正确,来自PDF高度,但其内容未呈现 我的应用程序必须在一系列web视图中显示非常短的PDF(假设这是一项强制性要求,我不能切换到其他任何内容。PDF是LaTex生成的,包含无法显示在UILabel中的文本等。此外,它们大约有4-5行长) 布局如下:有一个垂直滚动视图,其中有一个视图(内容视图)作为直接子视图。单个Ios UIWebView内容有时不呈现,ios,objective-c,pdf,uiwebview,Ios,Objective C,Pdf,Uiwebview,简而言之,我的问题是:加载到某些web视图中的某些pdf不会显示,而其他pdf会显示,如下图所示(请注意,我编辑的图像中放置了伪造的pdf内容,原始内容无法发布) 三个PDF已正确加载到三个UIWebView中 第二个UIWebView高度正确,来自PDF高度,但其内容未呈现 我的应用程序必须在一系列web视图中显示非常短的PDF(假设这是一项强制性要求,我不能切换到其他任何内容。PDF是LaTex生成的,包含无法显示在UILabel中的文本等。此外,它们大约有4-5行长) 布局如下:有一个
UIWebView
(黄色背景)嵌入到从UIView
继承的自定义类中(PDFView
,蓝色背景),因此我可以将该类指定为webview的委托,并在一个位置执行webview初始化+约束设置。webviewuserInteraction
已禁用。在内容视图中,我动态地为每个PDF添加一个PDFView
,设置约束并调用loadData:MIMEType:textcencodingname:baseURL:
,以加载PDF(从磁盘上的一个文件(白色框架)中加载为NSData
)。由于PDFView
是其UIWebView
的委托,当它完成加载其内容(pdf)时,我更改webview高度约束以匹配webview.scrollview.contentsize.height
。这允许我调整webview的大小,以便它显示整个PDF。Autolayout负责设置scrollviewcontentsize.height
,以便用户可以滚动整个pdf列表
一切似乎都很好,但有时,在某些Web视图上,内容没有呈现。当调用webViewDidFinishLoad:
触发时,webView.scrollView.contentSize.height
值是正确的(事实上,webView具有正确的高度),并且在autolayout完成其工作后,未呈现内容的webView框架具有正确的尺寸。这让我认为这一定是某种渲染问题,因为它似乎在不同的Web视图和不同的PDF上随机发生。有时我必须手动按下并弹出控制器,就像在问题出现前10次一样,有时它只是在第一次按下时出现。内存消耗似乎没有问题,并且没有任何内存警告
我检查了所有数据和视图:没有一个是零。此外,代理webView:didFailLoadWithError:
从未被调用,因此webView总是成功加载其内容(webviewdfinishload:
每次都被调用,即使对于不显示任何内容的webView也是如此)。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
#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
- (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;
}
控制器上的约束条件如下所示:
请注意,高度约束将在运行时删除
知道为什么会这样吗?你知道怎么解决吗
这里是我已经尝试过的:
loadContentView
,而不将pdfData加载到webview中。控制器出现后,将pdfData加载到WebView中李>
loadData:MIMEType:textcencodingname:baseURL:
作为第一个webview,等待webViewDidFinishLoad:
,然后对第二个webview重复此顺序,依此类推李>
我认为这不是一个问题。如果你一次发送多个请求,一个内容较少的请求将首先被加载。它还取决于网络连接。您可能需要的是在一个Web视图完成后开始加载每个Web视图。即使您将它们放在循环中,也不意味着所有的请求都将依次加载。这是我在第3点上所做的。循环中不会触发请求:当调用webViewDidfinishLoad:时,在前一个请求完成加载其内容后,会触发每个请求。此外,数据不是来自网络,而是来自内存(在WebView被实例化之前加载到控制器viewDidLoad中),您正在循环中调用initWithData。这意味着什么?我也没有看到在webViewDidFinishLoad中触发下一个请求的任何代码: