Reputation: 5558
Summary
I am currently faced with an issue that always worked fine in Objective-C, but I can't seem to get it to work in Swift (specifically v3). This is all built using Storyboards. I have two separate view controllers:
Currently, the SideMenu pops over, modally, on top of the ViewController and lists a set of actions via UIButtons. I guess I'll just go off of the most simplistic example, just to get the idea down. What I am trying to accomplish in this example is reloading the WKWebView (ViewController) from a UIButton tap (SideMenuTableView). Below is a more clear picture of what I am trying to get at if things are still unclear:
Currently, I can call the SideMenu with a simple Storyboard segue (Kind: Present Modally)
. Furthermore, I can dismiss the SideMenu which was implemented into a simple close()
function. However, when attempting to call the refresh function, I receive the following error message:
fatal error: unexpectedly found nil while unwrapping an Optional value
Code
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: Updated segue code.
// 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
}
}
}
Upvotes: 0
Views: 484
Reputation: 3050
You are initializing a new UIViewController
with ViewController().refresh()
. A delegate pattern is a nicer way to accomplish what you are trying:
Create a protocol:
protocol MainViewControllerDelegate /* Can be called whatever you like */ {
func refresh()
}
And make your ViewController
conform to it.
In your SideMenuTableView
create a variable to hold the reference to it's delegates.
weak var delegate: MainViewControllerDelegate?
In your prepareForSegue() function of ViewController
. Check to see if the destination segue is your SideMenuTableView
:
if let vc = destination.vc as? SideMenuTableView {
vc.delegate = self
}
Now in your @IBAction button tap in SideMenuTableView call the delegate method.
@IBAction func refresh(sender: AnyObject!) {
delegate?.refresh()
close()
}
Because your ViewController
conforms to this protocol (it has to have a refresh function in it's class), the refresh function will be executed.
Upvotes: 3