[ios] UIWebView의 콘텐츠 크기를 결정하는 방법은 무엇입니까?

나는이 UIWebView다른 (단일 페이지) 내용으로. CGSize부모 뷰의 크기를 적절하게 조정하기 위해 콘텐츠 를 찾고 싶습니다 . -sizeThatFits:불행히도 명백한 것은 webView의 현재 프레임 크기를 반환합니다.



답변

사용하는 첫 번째 추측 -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에게 감사) 이 있음을 지적해야합니다 . 어떤 솔루션이 더 잘 수행되는지 확실하지 않습니다.

두 가지 해키 솔루션 중 나는 이것을 더 좋아합니다.


답변

잘 작동하는 또 다른 솔루션이 있습니다.

한편으로 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 = NOscrollView.

다음은의 레이아웃을 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, 내가 추가 한 코드의 마지막 조각의 계산이었다 heightcontentSize내 사용자 지정의 scrollView이러한 내장 webViews, 그러나 그것은 쉽게로했다 합산 나의 webViewframe.size.height요령으로 계산 상술 …


답변

Ortwin의 대답이 대부분의 시간에만 작동한다는 것을 알았 기 때문에이 질문을 부활시키는 중 …

webViewDidFinishLoad방법은 한번 이상 호출 될 수 있고,에 의해 반환되는 첫 번째 값은 sizeThatFits최종 크기가되어야 하는지를의 일부분이다. 그런 다음 어떤 이유에서든 sizeThatFitswhen에 대한 다음 호출 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 버전에 해당하는지 확실하지 않은 경우 시도해보세요.


답변

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));
}


답변

AFAIK는 [webView sizeThatFits:CGSizeZero]콘텐츠 크기를 파악하는 데 사용할 수 있습니다 .


답변

이상 해요!

나는 솔루션을 테스트 모두 sizeThatFits:하고 [webView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight"]있습니다 NOT 나를 위해 작동합니다.

그러나 웹 페이지 콘텐츠의 높이를 적절하게 얻을 수있는 흥미롭고 쉬운 방법을 찾았습니다. 현재는 위임 메서드에서 사용했습니다 scrollViewDidScroll:.

CGFloat contentHeight = scrollView.contentSize.height - CGRectGetHeight(scrollView.frame);

iOS 9.3 시뮬레이터 / 기기에서 확인되었습니다. 행운을 빕니다!

편집하다:

배경 : html 콘텐츠는 내 문자열 변수와 HTTP 콘텐츠 템플릿으로 계산되며 메서드 loadHTMLString:baseURL:에 의해로드되며 등록 된 JS 스크립트가 없습니다.