Swift delegate calling fatal error - swift

I am trying to call a delegate function in Swift 3.0. While calling i am getting an error which states "fatal error: unexpectedly found nil while unwrapping an Optional value". I have gone through giving static values, dynamic values no use.
protocol getServiceDelegate{
func getService(_ ServiceTitle: String)
}
And i call this delegate in following manner.
self.delegate.getService("hello")
What i am doing here wrong. Below which i set the delegate.
func textServiceTapped(img: AnyObject)
{
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "ProviderMoreDetailsVC") as! ProviderMoreDetailsViewController
vc.delegate = self
navigationController?.pushViewController(vc,
animated: true)
}
func getService(_ ServiceTitle: String){
textService.text = ServiceTitle
}

I resolved the error by using below code
var delegate: getServiceDelegate?
sampleDelegateString = "hello"
self.delegate?.getService(sampleDelegateString!)

Related

Sign Out button to Present Login View Controller - Swift 5

Hi I'm kind of new to Swift and I can't figure this out. I am trying to create a sign out button that would take user to the login page. I used the following two methods but the first one doesn't do anything and the second one is throwing Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value and it refers to the code with the customButton:
//this one doesn't do anything
#objc func SignOut(){
let vc = self.storyboard?.instantiateViewController(identifier: "LoginViewController") as! LoginViewController
let appDelegate = UIApplication.shared.delegate
appDelegate?.window??.rootViewController = vc
}
//this one is throwing an error
let vc = CustomViewController()
self.present(vc, animated: true, completion: nil)
//the Fatal error refers to this code
override func viewDidLoad() {
super.viewDidLoad()
self.customButton.addTarget(self, action: #selector(customButtonPressed), for: .touchUpInside)
}
Also, I was wondering if AppDelegate is the right approach or if I should use SceneDelegate. Any help would be greatly appreciated.
Try to do this
#objc func SignOut(){
let vc = self.storyboard?.instantiateViewController(identifier: "LoginViewController") as! LoginViewController
self.view.window?.rootViewController = vc
}
let vc = self.storyboard?.instantiateViewController(identifier: "LoginViewController") as! LoginViewController
vc.modalPresentationStyle = .fullScreen
self.present(vc, animated: true, completion: nil)
Please make sure the identifier is matching the one inside storyboard for this viewController

How do you present a VC from Xib in Swift?

I am trying to present a VC from a Xib file but it's resulting in
Fatal error: Unexpectedly found nil while unwrapping an Optional value
#IBAction func viewCartBtnTapped(_ sender: Any) {
let cart = storyboard?.instantiateViewController(withIdentifier: "CartVC") as? CartVC
present(cart!, animated: true, completion: nil)
}
try below code, YourStoryBoradName should be the name of storyboard without ".storyboard" extension :
let storyBoard : UIStoryboard = UIStoryboard(name: "YourStoryBoradName", bundle:nil)
let viewController = storyBoard.instantiateViewController(withIdentifier: "CartVC")as! CartVC
self.present(viewController, animated: true, completion: nil)

Unexpectedly found nil while implicitly unwrapping an Optional value

I'm trying to use a Customizable PageMenuViewController in Swift from cocoapods :Link
I want to load my already made views but all I get is a blank page
this is the function to load views:
func viewControllers(forPageMenuController pageMenuController: PageMenuController) -> [UIViewController] {
let detailVC = HomeViewController()
let vc : UIViewController = detailVC as UIViewController
let detailVC1 = SearchViewController()
let vc1 : UIViewController = detailVC1 as UIViewController
return [vc ,vc1 , vc ,vc1 ]
}
and when I used a ViewController that contained a table view I get this error :
Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
Error
can someone help me please ?
I initiated my ViewControllers by storyboard and it worked. so instead of :
let detailVC = HomeViewController()
let vc : UIViewController = detailVC as UIViewController
I wrote :
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "HomeViewController")
and it worked but the page is still white nothing changed.
thank you Alexander

Swift: Can't use navigationController.pushViewController inside a function

I am transitioning between views programatically using the code below and it gets repeated quite a lot so I wanted to create a global function but I can't seem to be able to get the hang of it.
The code works when called inside a ViewController class, so I suppose the problem is that my function doesn't know which VC do I want to call navigationController.pushViewController on, but I don't know how to reference the VC either as an argument passed to the function, or better yet with something like .self to take the current VC class the function is called in.
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "ExamplesControllerVC")
self.navigationController?.pushViewController(vc, animated: true)
The error I get if I try to run that as a function in a separate file is:
Use of unresolved identifier 'navigationController'; did you mean 'UINavigationController'?
So the function I'd like to create and call is something like:
showVC("ExamplesControllerVC")
Any ideas?
Whatever function this code is in needs to be updated to take a parameter of type UIViewController.
func showMain(on vc: UIViewController) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "ExamplesControllerVC")
vc.navigationController?.pushViewController(vc, animated: true)
}
Now you can call this as:
showMain(on: someViewController)
Or add this function to an extension on UIViewController then your use of self works just fine.
extension UIViewController {
func showMain() {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "ExamplesControllerVC")
self.navigationController?.pushViewController(vc, animated: true)
}
}
Do you want to do something like this?:
extension UIViewController {
func presentView(withIdentifier: String) {
if let newVC = self.storyboard?.instantiateViewController(withIdentifier: withIdentifier) {
self.present(newVC, animated: true, completion: nil)
}
}
}
You can call it this way:
self.presentView(withIdentifier: "yourIdentifier")

Using present in UIViewController properly

I encounter the problem that I cannot present a dynamic UIViewController in my class using "self". It tells me "Value of type '(LoginScreenVC) -> () -> (LoginScreenVC)' has no member 'view'".
It would work using a closure like e.g. if let loginScreen = UIStoryBoard ..., but since the UIViewController to switch to is dynamic, I cannot cast it to a specific UIViewController.
is there any other way to present the ViewController?
This is my code:
SWIFT 4.2 / XCode 10.1
import UIKit
class LoginScreenVC: UIViewController {
let myTokenHandler = TokenHandler()
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func loginButton(_ sender: Any) {
print("Login button pressed")
let usernameInputField = self.view.viewWithTag(6548) as! UITextField
let passwordInputField = self.view.viewWithTag(6549) as! UITextField
userInput = usernameInputField.text!
passInput = passwordInputField.text!
// call completion handler
requestToken(success: handlerBlock)
}
// completion handler step 1: request token and get redirect string to switch screen
func requestToken(success: (String) -> Void) {
let requestResult = myTokenHandler.requestToken(password: passInput, username: userInput)
success(requestResult)
}
// completion handler step 2: use redirect string to switch screen
let handlerBlock: (String) -> Void = { redirect in
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let loginScreen = storyboard.instantiateViewController(withIdentifier: redirect)
self.present(loginScreen, animated: true, completion: nil) //Value of type '(LoginScreenVC) -> () -> (LoginScreenVC)' has no member 'view'
}
}
You are saying:
let handlerBlock: (String) -> Void = { redirect in
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let loginScreen = storyboard.instantiateViewController(withIdentifier: redirect)
self.present(loginScreen, animated: true, completion: nil)
}
The problem is that you are using the term self in a context where there is no self. (Well, there is a self, but it isn't what you think.) present is a UIViewController instance method, so self needs to be a UIViewController instance; and in this context, it isn't.
I can think of half a dozen ways to express the thing you're trying to express, but the simplest would probably be to rewrite that as:
func handlerBlock(_ redirect:String) -> Void {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let loginScreen = storyboard.instantiateViewController(withIdentifier: redirect)
self.present(loginScreen, animated: true, completion: nil)
}
Now handlerBlock is an instance method, and self is meaningful — it is the instance, which is just what you want. The rest of your code is unchanged, because the bare name handlerBlock in the expression requestToken(success: handlerBlock) is a function name, just as before.