답변:
사용하는 첫 번째 추측 -sizeThatFits:
이 완전히 잘못된 것은 아니라는 것이 밝혀졌습니다 . 작동하는 것처럼 보이지만 webView의 프레임이 -sizeThatFits:
. 그 후 피팅 크기로 잘못된 프레임 크기를 수정할 수 있습니다. 이것은 끔찍하게 들리지만 실제로 그렇게 나쁘지는 않습니다. 두 프레임 변경을 바로 수행하기 때문에 뷰가 업데이트되지 않고 깜박이지 않습니다.
물론 콘텐츠가로드 될 때까지 기다려야하므로 코드를 -webViewDidFinishLoad:
delegate 메서드에 넣습니다 .
Obj-C
- (void)webViewDidFinishLoad:(UIWebView *)aWebView {
CGRect frame = aWebView.frame;
frame.size.height = 1;
aWebView.frame = frame;
CGSize fittingSize = [aWebView sizeThatFits:CGSizeZero];
frame.size = fittingSize;
aWebView.frame = frame;
NSLog(@"size: %f, %f", fittingSize.width, fittingSize.height);
}
스위프트 4.x
func webViewDidFinishLoad(_ webView: UIWebView) {
var frame = webView.frame
frame.size.height = 1
webView.frame = frame
let fittingSize = webView.sizeThatFits(CGSize.init(width: 0, height: 0))
frame.size = fittingSize
webView.frame = frame
}
JavaScript를 사용하는 또 다른 접근 방식 (@GregInYEG에게 감사) 이 있음을 지적해야합니다 . 어떤 솔루션이 더 잘 수행되는지 확실하지 않습니다.
두 가지 해키 솔루션 중 나는 이것을 더 좋아합니다.
UIWebView
부모보기보다 높으면 UIScrollView
.
잘 작동하는 또 다른 솔루션이 있습니다.
한편으로 Ortwin의 접근 방식 및 솔루션은 iOS 6.0 이상에서만 작동하지만 iOS 5.0, 5.1 및 5.1.1에서는 제대로 작동하지 않으며 다른 한편으로는 내가 좋아하지 않고 이해할 수없는 것이 있습니다. Ortwin의 접근 방식에서는 [webView sizeThatFits:CGSizeZero]
매개 변수와 함께 메소드 를 사용하는 것입니다.이 메소드 와 매개 변수 CGSizeZero
에 대한 Apple 공식 문서를 읽으면 다음과 같이 명확하게 말합니다.
이 메서드의 기본 구현은 뷰 경계 사각형의 크기 부분을 반환합니다. 하위 클래스는이 메서드를 재정 의하여 원하는 하위 뷰의 레이아웃을 기반으로 사용자 지정 값을 반환 할 수 있습니다. 예를 들어 UISwitch 객체는 스위치 뷰의 표준 크기를 나타내는 고정 크기 값을 반환하고 UIImageView 객체는 현재 표시중인 이미지의 크기를 반환합니다.
내 말은 문서를 읽으면 전달 된 매개 변수가 [webView sizeThatFits: ...]
최소한 원하는 width
. 그 용액으로 원하는 폭이 설정되는 webView
호출 이전의 프레임 sizeThatFits
로모그래퍼 CGSizeZero
파라미터. 그래서 저는이 솔루션이 "우연히"iOS 6에서 작동하고 있다고 유지합니다.
iOS 5.0 이상에서 작동하는 이점이있는보다 합리적인 접근 방식을 상상했습니다. 또한 둘 이상의 webView (속성 webView.scrollView.scrollEnabled = NO
이 scrollView
.
다음은의 레이아웃을 webView
원하는대로 강제 설정 width
하고 해당 height
세트를 다시 가져 오는 코드 webView
입니다.
Obj-C
- (void)webViewDidFinishLoad:(UIWebView *)aWebView
{
aWebView.scrollView.scrollEnabled = NO; // Property available in iOS 5.0 and later
CGRect frame = aWebView.frame;
frame.size.width = 200; // Your desired width here.
frame.size.height = 1; // Set the height to a small one.
aWebView.frame = frame; // Set webView's Frame, forcing the Layout of its embedded scrollView with current Frame's constraints (Width set above).
frame.size.height = aWebView.scrollView.contentSize.height; // Get the corresponding height from the webView's embedded scrollView.
aWebView.frame = frame; // Set the scrollView contentHeight back to the frame itself.
}
스위프트 4.x
func webViewDidFinishLoad(_ aWebView: UIWebView) {
aWebView.scrollView.isScrollEnabled = false
var frame = aWebView.frame
frame.size.width = 200
frame.size.height = 1
aWebView.frame = frame
frame.size.height = aWebView.scrollView.contentSize.height
aWebView.frame = frame;
}
내 예에서이 있습니다 webView
사용자 정의에 포함 된 scrollView
다른 가지고 webViews
... 모든 이들은 webViews
자신이 있었다 webView.scrollView.scrollEnabled = NO
, 내가 추가 한 코드의 마지막 조각의 계산이었다 height
의 contentSize
내 사용자 지정의 scrollView
이러한 내장 webViews
, 그러나 그것은 쉽게로했다 합산 나의 webView
의 frame.size.height
요령으로 계산 상술 ...
-[UIWebView scrollView]
iOS 5.0 이상에서만 사용할 수 있습니다.
Ortwin의 대답이 대부분의 시간에만 작동한다는 것을 알았 기 때문에이 질문을 부활시키는 중 ...
webViewDidFinishLoad
방법은 한번 이상 호출 될 수 있고,에 의해 반환되는 첫 번째 값은 sizeThatFits
최종 크기가되어야 하는지를의 일부분이다. 그런 다음 어떤 이유에서든 sizeThatFits
when에 대한 다음 호출 webViewDidFinishLoad
은 이전과 동일한 값을 잘못 반환합니다! 이것은 일종의 동시성 문제인 것처럼 동일한 콘텐츠에 대해 무작위로 발생합니다. 시간이 지남에 따라이 동작이 변경되었을 수 있습니다. 제가 iOS 5 용으로 구축 중이고 sizeToFit
거의 동일한 방식으로 작동 한다는 것을 발견했기 때문입니다 (이전에는 그렇지 않았습니까?).
이 간단한 해결책을 결정했습니다.
- (void)webViewDidFinishLoad:(UIWebView *)aWebView
{
CGFloat height = [[aWebView stringByEvaluatingJavaScriptFromString:@"document.height"] floatValue];
CGFloat width = [[aWebView stringByEvaluatingJavaScriptFromString:@"document.width"] floatValue];
CGRect frame = aWebView.frame;
frame.size.height = height;
frame.size.width = width;
aWebView.frame = frame;
}
Swift (2.2) :
func webViewDidFinishLoad(webView: UIWebView) {
if let heightString = webView.stringByEvaluatingJavaScriptFromString("document.height"),
widthString = webView.stringByEvaluatingJavaScriptFromString("document.width"),
height = Float(heightString),
width = Float(widthString) {
var rect = webView.frame
rect.size.height = CGFloat(height)
rect.size.width = CGFloat(width)
webView.frame = rect
}
}
업데이트 : 댓글에서 언급했듯이 콘텐츠가 축소 된 경우를 파악하지 못하는 것 같습니다. 모든 콘텐츠 및 OS 버전에 해당하는지 확실하지 않은 경우 시도해보세요.
webView.scalesPageToFit = YES
위의 주석에서 언급 한 @Sijo로 제공하지 않을 때만 작동합니다 .
Xcode 8 및 iOS 10에서 웹보기의 높이를 결정합니다. 당신은 사용하여 높이를 얻을 수 있습니다
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
CGFloat height = [[webView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight"] floatValue];
NSLog(@"Webview height is:: %f", height);
}
또는 Swift
func webViewDidFinishLoad(aWebView:UIWebView){
let height: Float = (aWebView.stringByEvaluatingJavaScriptFromString("document.body.scrollHeight")?.toFloat())!
print("Webview height is::\(height)")
}
간단한 해결책은 그냥 사용하는 webView.scrollView.contentSize
것이지만 이것이 JavaScript에서 작동하는지 모르겠습니다. JavaScript가 사용되지 않으면 확실히 작동합니다.
- (void)webViewDidFinishLoad:(UIWebView *)aWebView {
CGSize contentSize = aWebView.scrollView.contentSize;
NSLog(@"webView contentSize: %@", NSStringFromCGSize(contentSize));
}
이상 해요!
나는 솔루션을 테스트 모두 sizeThatFits:
하고 [webView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight"]
있습니다 NOT 나를 위해 작동합니다.
그러나 웹 페이지 콘텐츠의 높이를 적절하게 얻을 수있는 흥미롭고 쉬운 방법을 찾았습니다. 현재는 위임 메서드에서 사용했습니다 scrollViewDidScroll:
.
CGFloat contentHeight = scrollView.contentSize.height - CGRectGetHeight(scrollView.frame);
iOS 9.3 시뮬레이터 / 기기에서 확인되었습니다. 행운을 빕니다!
편집하다:
배경 : html 콘텐츠는 내 문자열 변수와 HTTP 콘텐츠 템플릿으로 계산되며 메서드 loadHTMLString:baseURL:
에 의해로드되며 등록 된 JS 스크립트가 없습니다.
에 UIWebView
대한 HTML 콘텐츠의 크기를 결정하기 위해 하위 뷰가 아니므로 (따라서 창 계층의 일부가 아님)을 사용하고 UITableViewCells
있습니다. 연결 UIWebView
이 끊어진 파일 이 -[UIWebView sizeThatFits:]
. 또한 https://stackoverflow.com/a/3937599/9636 에서 언급했듯이 적절한 높이를 얻으려면 UIWebView
's frame
height
를 1로 설정해야합니다 .
는 IF UIWebView
의 높이가 너무 큰 (즉, 당신은 1000으로 설정되어 있지만, HTML 콘텐츠 크기는 500입니다) :
UIWebView.scrollView.contentSize.height
-[UIWebView stringByEvaluatingJavaScriptFromString:@"document.height"]
-[UIWebView sizeThatFits:]
모두 height
1000을 반환합니다 .
이 경우 내 문제를 해결하기 위해 https://stackoverflow.com/a/11770883/9636을 사용 하여 성실하게 투표했습니다. 그러나이 솔루션 UIWebView.frame.width
은 -[UIWebView sizeThatFits:]
width
.
여기에 제시된 제안 중 어느 것도 내 상황에 도움이되지 않았지만 답을 얻을 수있는 내용을 읽었습니다. 고정 된 UI 컨트롤 집합과 UIWebView가있는 ViewController가 있습니다. UI 컨트롤이 HTML 콘텐츠에 연결된 것처럼 전체 페이지가 스크롤되기를 원했기 때문에 UIWebView에서 스크롤을 비활성화 한 다음 부모 스크롤 뷰의 콘텐츠 크기를 올바르게 설정해야합니다.
중요한 팁은 UIWebView가 화면에 렌더링 될 때까지 크기를 올바르게보고하지 않는다는 것입니다. 그래서 콘텐츠를로드 할 때 콘텐츠 크기를 사용 가능한 화면 높이로 설정했습니다. 그런 다음 viewDidAppear에서 scrollview의 콘텐츠 크기를 올바른 값으로 업데이트합니다. 로컬 콘텐츠에서 loadHTMLString을 호출하기 때문에 이것은 나를 위해 일했습니다. loadRequest를 사용하는 경우 html이 검색되는 속도에 따라 webViewDidFinishLoad의 contentSize도 업데이트해야 할 수 있습니다.
스크롤 뷰의 보이지 않는 부분 만 변경되기 때문에 깜박임이 없습니다.
webViewDidFinishLoad
안전한 접근 방식으로 의존하고 싶습니다 .
HTML에 iframe (예 : facebook-, twitter, instagram-embeds)과 같은 무거운 HTML 콘텐츠 가 포함 된 경우 실제 솔루션이 훨씬 더 어렵습니다. 먼저 HTML을 래핑합니다.
[htmlContent appendFormat:@"<html>", [[LocalizationStore instance] currentTextDir], [[LocalizationStore instance] currentLang]];
[htmlContent appendFormat:@"<head>"];
[htmlContent appendString:@"<script type=\"text/javascript\">"];
[htmlContent appendFormat:@" var lastHeight = 0;"];
[htmlContent appendFormat:@" function updateHeight() { var h = document.getElementById('content').offsetHeight; if (lastHeight != h) { lastHeight = h; window.location.href = \"x-update-webview-height://\" + h } }"];
[htmlContent appendFormat:@" window.onload = function() {"];
[htmlContent appendFormat:@" setTimeout(updateHeight, 1000);"];
[htmlContent appendFormat:@" setTimeout(updateHeight, 3000);"];
[htmlContent appendFormat:@" if (window.intervalId) { clearInterval(window.intervalId); }"];
[htmlContent appendFormat:@" window.intervalId = setInterval(updateHeight, 5000);"];
[htmlContent appendFormat:@" setTimeout(function(){ clearInterval(window.intervalId); window.intervalId = null; }, 30000);"];
[htmlContent appendFormat:@" };"];
[htmlContent appendFormat:@"</script>"];
[htmlContent appendFormat:@"..."]; // Rest of your HTML <head>-section
[htmlContent appendFormat:@"</head>"];
[htmlContent appendFormat:@"<body>"];
[htmlContent appendFormat:@"<div id=\"content\">"]; // !important https://stackoverflow.com/a/8031442/1046909
[htmlContent appendFormat:@"..."]; // Your HTML-content
[htmlContent appendFormat:@"</div>"]; // </div id="content">
[htmlContent appendFormat:@"</body>"];
[htmlContent appendFormat:@"</html>"];
그런 다음 shouldStartLoadWithRequest에 x-update-webview-height -scheme 처리를 추가 합니다 .
if (navigationType == UIWebViewNavigationTypeLinkClicked || navigationType == UIWebViewNavigationTypeOther) {
// Handling Custom URL Scheme
if([[[request URL] scheme] isEqualToString:@"x-update-webview-height"]) {
NSInteger currentWebViewHeight = [[[request URL] host] intValue];
if (_lastWebViewHeight != currentWebViewHeight) {
_lastWebViewHeight = currentWebViewHeight; // class property
_realWebViewHeight = currentWebViewHeight; // class property
[self layoutSubviews];
}
return NO;
}
...
마지막으로 layoutSubviews 안에 다음 코드를 추가하십시오 .
...
NSInteger webViewHeight = 0;
if (_realWebViewHeight > 0) {
webViewHeight = _realWebViewHeight;
_realWebViewHeight = 0;
} else {
webViewHeight = [[webView stringByEvaluatingJavaScriptFromString:@"document.getElementById(\"content\").offsetHeight;"] integerValue];
}
upateWebViewHeightTheWayYorLike(webViewHeight);// Now your have real WebViewHeight so you can update your webview height you like.
...
PS ObjectiveC / Swift 코드 내에서 시간 지연 (SetTimeout 및 setInterval)을 구현할 수 있습니다.
PSS UIWebView 및 Facebook Embeds에 대한 중요 정보 : 포함 된 Facebook 게시물이 UIWebView에서 제대로 표시되지 않습니다.
나는 또한이 문제에 갇혀 있었고, webView의 동적 높이를 계산하려면 먼저 webView의 너비를 알려야하므로 js 앞에 한 줄을 추가하면 얻을 수 있음을 알았습니다. 매우 정확한 실제 높이.
코드는 다음과 같이 간단합니다.
-(void)webViewDidFinishLoad:(UIWebView *)webView
{
//tell the width first
webView.width = [UIScreen mainScreen].bounds.size.width;
//use js to get height dynamically
CGFloat scrollSizeHeight = [[webView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight"] floatValue];
webView.height = scrollSizeHeight;
webView.x = 0;
webView.y = 0;
//......
}
또한 언급 된 모든 방법의 올바른 작동을 위해 iOS 7에서 뷰 컨트롤러 viewDidLoad
메서드에 다음을 추가하십시오 .
if ([self respondsToSelector:@selector(automaticallyAdjustsScrollViewInsets)]) {
self.automaticallyAdjustsScrollViewInsets = NO;
}
그렇지 않으면 어떤 방법도 제대로 작동하지 않습니다.