Как настроить WKWebView для заполнения NSWindow?

У меня есть небольшое приложение-прототип, разработанное на Swift с XCode 7.2. Приложение было создано как документное приложение Cocoa с раскадровкой. Таким образом, проект содержит AppDelegate.swift, Document.swift и Main.storyboard, все из которых не изменились по сравнению с тем, что сгенерировал XCode, и ViewController.swift, который содержит это:

import Cocoa
import WebKit

class ViewController: NSViewController {

    var webView: WKWebView {
        return view as! WKWebView
    }

    override func loadView() {
        view = WKWebView(/*frame: CGRect(x: 0, y: 0, width: 200, height: 200)*/)
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        webView.loadHTMLString("<html><body><p>Hello, World!</p></body></html>", baseURL: nil)
    }
}

Я переопределил loadView(), чтобы напрямую создать WKWebView и назначить его свойству view ViewController в качестве корневого представления, а не загружать представление, определенное в раскадровке.

Обратите внимание, что аргумент frame для WKWebView может быть прокомментирован или удален, чтобы продемонстрировать различные варианты поведения, лежащие в основе этого вопроса.

Желаемое поведение

Экземпляр WKWebView должен заполнять окно, соответствующее каждому документу, а начальный размер и положение окон нового документа должны быть такими же, как и для NSWindow в раскадровке (480x270 при (196, 240)). Размер WKWebView должен изменяться вместе с окружающим окном.

Наблюдаемое поведение

Без аргумента frame

Без аргумента frame окно документа не отображается при запуске приложения, хотя меню "Окно" показывает, что был создан документ "Без названия". Окна документов также не отображаются, когда другие документы (Без названия 2 и т. д.) создаются с помощью Файл > Создать.

Однако, если документ отображается в полноэкранном режиме с помощью Просмотр > Войти в полноэкранный режим, WKWebView и его приветствие отображаются должным образом.

С аргументом frame

С аргументом frame окна документа, содержащие WKWebView и его приветствие, отображаются с размером и положением, указанными в CGRect.

Вопрос

Я не понимаю, почему, когда рамка WKWebView не указана, вид принудительно подгоняется под размер контейнера (экрана) в полноэкранном режиме, а в оконном режиме вроде бы происходит наоборот: Окно принудительно к (вырожденному?) размеру представления, и поэтому становится невидимым. Я ожидал, что новые представления примут размер окна, определенный в раскадровке.

В моем ViewController, как мне настроить экземпляры WKWebView, чтобы заполнить NSWindow, которые структура документа создает в соответствии с каждым NSDocument? Или, возможно, мой подход ошибочен, и мне следует настроить начальный размер окна с помощью размера представления в ViewController.loadView()?


person Rob Smallshire    schedule 15.02.2016    source источник
comment
Пожалуйста, проверьте мой ответ.   -  person Pradeep K    schedule 25.02.2016
comment
Подойдет, но сейчас я далеко от компьютера, поэтому не могу проверить.   -  person Rob Smallshire    schedule 25.02.2016


Ответы (2)


Попробуйте этот метод. Сначала вы должны вызвать super.loadView(). Это даст вам начальный размер представления, загружаемого из раскадровки. Затем вы меняете само представление на веб-представление, используя рамку исходного представления. Надеюсь, это решит вашу проблему.

override func loadView() {
    super.loadView()
    view = WKWebView(frame:self.view.frame)
}

Вы также можете попробовать установить цвет фона веб-представления, чтобы убедиться, что он работает.

webView.loadHTMLString("<html><body bgcolor=red><p>Hello, World!</p></body></html>", baseURL: nil)

person Pradeep K    schedule 24.02.2016
comment
Если вы сможете убедить меня, что вы действительно пробовали это на Mac и что это работает, я приму этот ответ. Следующие несколько дней я не буду пользоваться своим Mac, поэтому не могу проверить это сам. - person Rob Smallshire; 25.02.2016
comment
Да, я сделал это на Mac и ответил. Вот видео приложения. filedropper.com/untitled480p - person Pradeep K; 26.02.2016

Поэтому моей первой реакцией было: почему бы вам просто не добавить WKWebView в раскадровку? Таким образом, вы можете изменить его размер так, чтобы он соответствовал размеру окружающего окна. Оказывается, вы не можете добавить WKWebView в Interface Builder (поэтому я думаю, что вам пришлось пойти по этому пути).

loadView по умолчанию подключает созданное представление из пера к свойству представления контроллера представления. Проблема с переопределением loadView и последующим назначением self.view заключается в том, что это нарушает отношения раскадровки, которые имеет содержимое окна с вашим ViewController.

Таким образом, решение состоит в том, чтобы дождаться загрузки self.view из раскадровки, а затем добавить WKWebView в качестве подпредставления:

- (void)viewDidLoad {
    WKWebView *wb = [[WKWebView alloc] initWithFrame:self.view.frame];
    [wb loadHTMLString:@"<html><body><p>Hello, World!</p></body></html>" baseURL:nil];
    [self.view addSubview:wb];
}

У меня есть только Objective-C. Извините, еще не изучил Swift.

person rocky    schedule 20.02.2016
comment
Проблема с этим методом заключается в том, что он не изменяет размер при изменении размера окна. Что исходный вопрос пытается сделать, так это изменить представление самого ViewController на веб-представление. - person Pradeep K; 25.02.2016
comment
Исходный вопрос спрашивает, как заставить WKWebView заполнить содержащее его окно, используя размеры и позиции окна, указанные в раскадровке, что и делает мой код. Ни о каком изменении размера речи не идет. - person rocky; 25.02.2016
comment
Изменение размера действительно требуется. Размер окна в раскадровке можно изменять, поэтому размер WKWebView должен изменяться вместе с ним, как говорит Прадип. - person Rob Smallshire; 25.02.2016
comment
Как я уже сказал, ничто в вопросе не требует этого. Если вам нужно изменить размер, отредактируйте свой вопрос. - person rocky; 25.02.2016
comment
@rocky Как насчет предложения WKWebView должен изменять размер окружающего окна? - person Rob Smallshire; 28.02.2016