2017-02-12 26 views
0

Я новый Swift разработчик реализует основные части Safari с WKWebView (мне нужно взаимодействовать между Javascript & Swift, поэтому SFSafariViewController не вариант), и я пытаюсь объявить все элементы программным путем.Swift 3, IOS, 10 - программно объявлены UIStackView не фитинга ширину экрана

Для имитации поиска бар и прогресс бар Safari, я хочу, чтобы установить UISearchBar, сложенные на вершине UIProgressView, как titleView для UIViewController «s UINavigationItem. Я могу управлять им только одним элементом, но не со стеком из двух элементов.

Вот как выглядит мой проект прямо сейчас. UISearchBar и UIProgressView либо слишком широкие или слишком тонкие, чтобы заполнить UINavigationBar должным образом, в зависимости от вращения:

Portrait view Landscape view

Вот мой код ViewController.swift:

import WebKit 
import UIKit 

class ViewController: UIViewController, WKNavigationDelegate, UISearchBarDelegate { 
    var searchBar: UISearchBar = UISearchBar() 
    var progressView: UIProgressView = UIProgressView(progressViewStyle: .bar) 
    var stackView: UIStackView = UIStackView() 
    var webView: WKWebView! 

    override func loadView() { 
     webView = WKWebView() 
     webView.navigationDelegate = self 
     view = webView 
    } 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     /** Watches for changes in the WKWebView.estimatedProgress variable, and */ 
     webView.addObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress), options: .new, context: nil) 

     /** Initialise toolbar elements */ 
     let spacer = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) 
     let refresh = UIBarButtonItem(barButtonSystemItem: .refresh, target: webView, action: #selector(webView.reload)) 
     toolbarItems = [spacer, refresh] 
     navigationController?.isToolbarHidden = false 

     /** Initialise the UISearchBar */ 
     searchBar.delegate = self // not clear yet whether setting this is necessary. 
     searchBar.searchBarStyle = UISearchBarStyle.minimal 
     searchBar.showsCancelButton = true 
     searchBar.widthAnchor.constraint(equalToConstant: (navigationController?.navigationBar.bounds.width)!).isActive = true 
     // searchBar.heightAnchor.constraint(equalToConstant: 44.0).isActive = true 
     // searchBar.sizeToFit() 

     /** Initialise the UIProgressView */ 
     progressView.widthAnchor.constraint(equalToConstant: (navigationController?.navigationBar.bounds.width)!).isActive = true 
     // progressView.heightAnchor.constraint(equalToConstant: 4.0).isActive = true 
     // progressView.sizeToFit() 

     /** Add the UISearchBar & UIProgressView to the UIStackView, then initialise it and finally set it as the UINavigationItem's titleView.*/ 
     stackView.axis = UILayoutConstraintAxis.vertical 
     stackView.alignment = UIStackViewAlignment.center 
     stackView.distribution = UIStackViewDistribution.fillProportionally 
     stackView.addArrangedSubview(searchBar) 
     stackView.addArrangedSubview(progressView) 
     stackView.translatesAutoresizingMaskIntoConstraints = false; 
     /* These two constraints are causing a crash, so disabling them for now. */ 
     // stackView.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true 
     // stackView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor).isActive = true 
     navigationItem.titleView = stackView 

     navigationController?.hidesBarsOnSwipe = true 

     let url = URL(string: "https://en.wikipedia.org")! 
     webView.load(URLRequest(url: url)) 
     webView.allowsBackForwardNavigationGestures = true 
    } 

    /** Updates the UIProgressView. */ 
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { 
     // keyPath "estimatedProgress" is equivalent to #keyPath(WKWebView.estimatedProgress) 
     if keyPath == "estimatedProgress" { 
      // progressView.isHidden = webView.estimatedProgress == 1 // if we want to hide upon 100% 
      progressView.progress = Float(webView.estimatedProgress) 
     } 
    } 

    /** Sets the webView's title upon navigation finishing. */ 
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { 
     title = webView.title 
    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
     // Dispose of any resources that can be recreated. 
    } 

} 

Примечание: любое принятое решение должно продолжаться до отобразите стек элементов правильно после обратного вызова, чтобы скрыть UINavigationBar, инициированный navigationController?.hidesBarsOnSwipe, т.е. когда пользователь выполняет жестовый салфет на WKWebView.

ответ

0

Докладывая с моим последним кодом, с благодарностью руководимого solution, представленной на Reddit автор Hacking With Swift:

class ViewController: UIViewController, UISearchBarDelegate { 
    var webView: WKWebView? 
    var searchBar: UISearchBar? 
    var progressView: UIProgressView? 

    override func loadView() { 
     super.loadView() 
     setUpWebView() 
     view = self.webView! // TODO: fix constraints error when video is run. 

     setUpSearchbar() 
     setUpProgressView() 

     let url = URL(string: "http://www.bbc.com")! 
     webView!.load(URLRequest(url: url)) 
    } 

    func setUpWebView(){ 
     webView = WKWebView() 
    } 

    func setUpSearchbar(){ 
     searchBar = UISearchBar() 
     searchBar!.delegate = self 
    } 

    func setUpProgressView() { 
     webView!.addObserver(self, forKeyPath: #keyPath(WKWebView.estimatedProgress), options: .new, context: nil) 
     guard let bar = navigationController?.navigationBar else { return; } 

     progressView = UIProgressView(progressViewStyle: .bar) 
     progressView!.translatesAutoresizingMaskIntoConstraints = false 
     bar.addSubview(progressView!) 

     progressView!.leadingAnchor.constraint(equalTo: bar.leadingAnchor).isActive = true 
     progressView!.trailingAnchor.constraint(equalTo: bar.trailingAnchor).isActive = true 
     progressView!.bottomAnchor.constraint(equalTo: bar.bottomAnchor).isActive = true 
    } 

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { 
     if keyPath == "estimatedProgress" { 
      // progressView.isHidden = webView.estimatedProgress == 1 /* Optional. This hides progressView on 100% */ 
      progressView!.progress = Float((webView?.estimatedProgress)!) 
     } 
    } 
}