2017-01-16 5 views
0

РезюмеФатальная ошибка при попытке вызова функции зрения контроллера от контроллера представления внешнего модального

В настоящее время я столкнулся с проблемой, которая всегда работала хорошо в Objective-C, но я не могу показаться, чтобы получить он работает в Swift (в частности, v3). Все это построено с помощью раскадровки. У меня есть две отдельные контроллеры Вид:

  1. ViewController: WKWebView & UIButtonItems
  2. SideMenuTableView: UITableView & UIButtons

В настоящее время SideMenu появляется снова, покадрово, на вершине ViewController и перечисляет набор действий через UIButtons. Думаю, я просто уйду из самого упрощенного примера, просто чтобы убрать эту идею. В этом примере я пытаюсь перезагрузить WKWebView (ViewController) из крана UIButton (SideMenuTableView). Ниже приводится более четкое представление о том, что я пытаюсь получить в если что-то до сих пор неясно:

Screenshots.png

В настоящее время я могу назвать SideMenu с простой раскадровки Segue (Kind: Present Modally). Кроме того, я могу отклонить SideMenu, который был реализован в простой функции close(). Однако, при попытке вызвать функцию обновления, я получаю следующее сообщение об ошибке:

fatal error: unexpectedly found nil while unwrapping an Optional value 

код

import UIKit 
import WebKit 

class ViewController: UIViewController, UINavigationControllerDelegate, WKNavigationDelegate { 

    var webView: WKWebView! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     let webURL = URL(string: "https://google.ca") 
     let webRequest = URLRequest(url: webURL!) 
     webView.load(webRequest) 

    func refresh() { 
     webView.reload() 
    } 
} 



import Foundation  

class SideMenuTableView: UITableViewController { 

    @IBAction fileprivate func close() { 
     self.dismiss(animated: true, completion: nil) 
    } 

    @IBAction func refresh(sender: AnyObject!) { 
     ViewController().refresh() 
     close() 
    } 
} 

EDIT: Обновленный переход кода.

// MARK: - Navigation 

    // In a storyboard-based application, you will often want to do a little preparation before navigation 
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 
     // Get the new view controller using segue.destinationViewController. 
     // Pass the selected object to the new view controller. 
     if let vc = segue.destination as? SideMenuTableView { 
      vc.delegate = self 
     } 
    } 
} 
+1

Возможный дубликат [Что делает «фатальная ошибка: неожиданно найденная нуль при разворачивании необязательного значения» означает?] (Http://stackoverflow.com/questions/32170456/what-does-fatal-error-unexpectedly-found- nil-while-unwrapping-an-optional-valu) – JAL

+2

BTW 'ViewController(). refresh()' не имеет никакого смысла. Вы инициализируете ** новый контроллер представления ** и вызываете 'refresh' на нем? – JAL

+0

Спасибо @JAL! Мне было интересно, что я делаю именно с этим кодом. –

ответ

3

Вы инициализирует новый UIViewController с ViewController().refresh(). Шаблон Делегат является более хорошим способом сделать то, что вы пытаетесь:

Создание протокола:

protocol MainViewControllerDelegate /* Can be called whatever you like */ { 
    func refresh() 
} 

и сделать свой ViewController соответствовать ей.

В вашей SideMenuTableView создайте переменную, чтобы удерживать ссылку на ее делегатов.

weak var delegate: MainViewControllerDelegate? 

В вашем prepareForSegue() функция ViewController. Проверьте, чтобы увидеть, если переход назначения вашего SideMenuTableView:

if let vc = destination.vc as? SideMenuTableView { 
    vc.delegate = self 
} 

Теперь в вашей кнопке @IBAction крана в SideMenuTableView вызвать метод делегата.

@IBAction func refresh(sender: AnyObject!) { 
     delegate?.refresh() 
     close() 
} 

Потому что ваш ViewController соответствует этому протоколу (он должен иметь функцию обновления в своем классе), функция обновления будет выполнена.

+0

Ах! Это было решение, которое я искал! Теперь, с точки зрения новичков, куда мне идти, чтобы реализовать протокол, а также совместив его с ViewController? Я помещаю его как фрагмент типа расширения внутри ViewController или размещаю его в AppDelegate? –

+0

Я обычно размещаю свои протоколы в том же файле ниже моего класса, что и делегат. Вы соглашаетесь с этим, написав свое имя протола за именем класса, как это было с другими делегатами. Затем создайте функцию с тем же именем и параметрами, которые описаны в протоколе, но теперь в вашем классе. – Emptyless

+0

Большое спасибо! Я всегда задавался вопросом о правильном размещении расширений, протоколов и тому подобных. –

Смежные вопросы