假设我有一个针对UIImageView(或其他视图)堆叠的UIWebView:
我想调整UIWebView的大小,以便知道放置UIImageView的位置。我这样做的方法是等待UIWebView完成加载:
webViewCalculating = YES;
while (webViewCalculating == YES) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
然后根据this suggestion
,在UIWebView完成加载后调整大小-(void)webViewDidFinishLoad:(UIWebView *)webView
{
CGRect frame = webView.frame;
frame.size.height = 1;
webView.frame = frame;
CGSize fittingSize = [webView sizeThatFits:CGSizeZero];
frame.size = fittingSize;
webView.frame = frame;
heightSoFar += webView.frame.size.height;
webViewCalculating = NO;
}
在此之后,我知道我的UIWebView有多高,我可以相应地放置我的UIImageView。但是,当我推送另一个视图控制器并回到此状态时,我的hacky [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
似乎不等到我的webView首先完成计算高度。有没有更好的方法让我知道我的UIWebView的大小而不等待它加载?也许类似于NSString的sizeWithFont
方法?
答案 0 :(得分:4)
你不应该做正在循环的while循环。这是一个非常糟糕的主意。在webview完成加载时,您应该让滚动视图容器响应并重新布局子视图。从“合理大小的webview区域”开始。也许在网页内容加载时显示一个微调器。
我以前用过的技术如下:
首先在UIWebView中添加一些类别方法,如下所示:
@interface UIWebView (ContentSize)
- (CGFloat)documentOffsetHeight;
@end
@implementation UIWebView (ContentSize)
- (CGFloat)documentOffsetHeight
{
return [[self stringByEvaluatingJavaScriptFromString:@"document.documentElement.offsetHeight"] floatValue];
}
@end
然后我编写了一个包含UIWebView的UIView子类。例如:
@interface MyWebView : UIView <UIWebViewDelegate>
@end
@implementation MyWebView
{
BOOL _loaded;
UYIWebView *_webView;
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
_webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, 1)];
_webView.delegate = self;
_webView.alpha = 0.0f;
[self addSubview:_webView]
}
}
- (CGSize)sizeThatFits:(__unused CGSize)size
{
if (_loaded)
{
CGFloat height = [webView_ documentOffsetHeight];
CGFloat width = self.frame.size.width;
return CGSizeMake(width, height);
}
return self.frame.size;
}
- (void)sizeToFit
{
CGSize fittingSize = [self sizeThatFits:CGSizeZero];
self.bounds = CGRectMake(0, 0, fittingSize.width, fittingSize.height);
}
- (void)layoutSubviews
{
[super layoutSubviews];
_webView.frame = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height);
}
- (void)loadHTMLString:(NSString *)htmlString baseURL:(NSURL *)baseURL
{
// This code assumes jQuery is already used in the HTML content. If not, added it as a script resource here too.
NSString *scriptTag = @"<script type=\"text/javascript\" >jQuery(document).ready(function() { window.location = 'x-webview://ready'; });</script>\n";
NSString *const headOpeningTag = @"<head>";
if ([htmlString rangeOfString:headOpeningTag].location != NSNotFound )
{
htmlString = [htmlString stringByReplacingOccurrencesOfString:headOpeningTag
withString:[headOpeningTag stringByAppendingString:headContent]
options:NSCaseInsensitiveSearch
range:NSMakeRange(0, [htmlString length])];
}
else
{
htmlString = [headContent stringByAppendingString:htmlString];
}
[_webView loadHTMLString:htmlString baseURL:baseURL];
}
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
if ([request.URL.scheme isEqualToString:@"x-webview"] && [request.URL.host isEqualToString:@"ready"])
{
_loaded = YES;
[UIView animateWithDuration:0.1
delay:0
options:UIViewAnimationOptionAllowUserInteraction
animations:^{ webView.alpha = 1.0f; }
completion:nil];
[self sizeToFit];
return NO;
}
return YES;
}
@end
所以这个UIView子类的功能基本上是嵌入一个不可见的_webview。然后,当文档加载并呈现时,基于jQuery的JavaScript尝试使用自定义URL方案离开当前页面。此导航被拒绝。但作为响应,视图大小适合并从HTML文档中获得适当的大小。
请注意,您不必使用jQuery。您可以添加DOM JavaScript事件。我只是更熟悉jQuery如何处理原始DOM事件。
在您的情况下,您必须与滚动视图通信内容已完成加载,并且滚动视图视图应重新布局。您可以使用委托协议或类似方法执行此操作。或者,scrollview可能是“MyWebView”容器UIView的子类。根据需要进行调整。
答案 1 :(得分:0)
属性未重置,因此当您返回此控制器时,您需要webViewCalculating = YES;
这样它就不会立即使while循环失败。
如果您已经这样做,可以尝试使用
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
中的
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
}
委托方法
希望这很有用。