present(_:animated:completion:) not working in Swift 3 - ios

So, when I try to use the present() function in Swift, it always crashes. Here's my code
func infoOpener(sender: UISwipeGestureRecognizer) {
let location: CGPoint = sender.location(in: tableView)
let cellPath: IndexPath = tableView.indexPathForRow(at: location)!
let VC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "userInfo") as! userInfoVC
VC.username = "#\(self.user[cellPath.row].username)"
VC.imageUrl = self.user[cellPath.row].imagePath
self.present(VC, animated: false, completion: nil)
}
Whenever I use the present(_:animated:completion:) function, I get an EXC_BREAKPOINT error. Can somebody help me out?

Use if let or guard let instead of force unwrapping Optionals with ! to make your code more robust:
func infoOpener(sender: UISwipeGestureRecognizer) {
let location: CGPoint = sender.location(in: tableView)
guard let cellPath: IndexPath = tableView.indexPathForRow(at: location) else {
print("No index path found")
return
}
guard let VC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "userInfo") as? userInfoVC else {
print("View controller could not be instantiated")
return
}
VC.username = "#\(self.user[cellPath.row].username)"
VC.imageUrl = self.user[cellPath.row].imagePath
self.present(VC, animated: false, completion: nil)
}

func infoOpener(sender: UISwipeGestureRecognizer) {
let location: CGPoint = sender.location(in: tableView)
let cellPath: IndexPath = tableView.indexPathForRow(at: location)!
if sender.state == .ended /*present in touch end*/ {
let VC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "userInfo") as! userInfoVC
VC.username = "#\(self.user[cellPath.row].username)"
VC.imageUrl = self.user[cellPath.row].imagePath
self.present(VC, animated: false, completion: nil)
}
}

You say your error is: "fatal error: unexpectedly found nil while unwrapping an Optional value"
The problem is probably not with present() method but some IBOutlet or variable on your ViewController.
Check all your outlets are connected properly or that what you are setting on "username" and "imageURL" is not nil if this variables do not accept nil.

Related

Swift: Thread 1: signal SIGABRT after storyBoard.instantiateViewController

I want switch user to another page
I use this code :
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let vcAboutUs = storyBoard.instantiateViewController(withIdentifier: "ViewControllerIndex")
self.present(vcAboutUs, animated: true, completion: nil)
But after run project i am getting Thread 1: signal SIGABRT error and simulator crashed
Image : https://i.stack.imgur.com/d1uIT.jpg
Full code :
DispatchQueue.global(qos: .background).async {
let getJsonLogin = GetData()
let result = getJsonLogin.getJson(urlGet: AppDelegate.ADDRESS+"/index.php", urlData: "mobile="+mobile+"&code="+getCode+"") { result in
DispatchQueue.main.async {
if(result == nil){
self.progressText.text = "Error";
} else {
if((result!["error"]!) == "true"){
self.progressTextCode.text = result!["message"]!;
} else {
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let vcAboutUs = storyBoard.instantiateViewController(withIdentifier: "ViewControllerIndex")
self.present(vcAboutUs, animated: true, completion: nil)
}
}
}
}
Did you add the name of VC to the storyboard?

Unable to Instantiate View Controller

I have a function, whereby I check if the UserDefaults are set and if not a new View Controller opens and presents a login screen which will set the user defaults.
My problem is the view controller does not Instantiate but I get a print "User not registered"
func checkUserAccount() {
let defaults = UserDefaults.standard
let accountName = defaults.bool(forKey: "PUserAccountName")
let accountPassword = defaults.bool(forKey: "PUserAccountPassword")
if accountName == true && accountPassword == true {
print("User Registered")
} else {
let storyboard: UIStoryboard = UIStoryboard(name: "PolTRiM", bundle: nil)
let vc: StudentLoginVC = storyboard.instantiateViewController(withIdentifier: "studentLogin") as! StudentLoginVC
vc.modalPresentationStyle = .custom
vc.modalTransitionStyle = .crossDissolve
self.present(vc, animated: true, completion: { _ in })
print("User not registered")
}
}
Any thoughts?
Have you double checked UIStoryBoard name and UIViewController identifier if it's written correctly? Otherwise this code is working for me
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let viewController = storyboard.instantiateViewController(withIdentifier :"MyViewController") as! UIViewController
self.present(viewController, animated: true)

Moving to another storyboard inside closure

api.postUserLogin(Parameters: params) { (json) in
print(json)
if (json["status"].string == "true") {
self.user.id = json["data"]["id"].string
self.user.verify_status = json["data"]["verify_status"].string
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "MainViewController") as UIViewController
present(vc, animated: true, completion: nil)
}
}
Try this code:
func callViewController(){
let viewController: UIViewController = UIStoryboard(name:"STORYBOARD_NAME",bundle:nil).instantiateViewController(withIdentifier: "MainViewController")
let window :UIWindow = UIApplication.shared.keyWindow!
window.rootViewController = viewController
window.makeKeyAndVisible()
}

Touch Id autotrigger success when i dismiss from another view

the process is :
1 the user login with touch id
2 the user logout (logout dismiss to login)
then the app autotrigger touch id with success response (this not happen in the emulators) HELP!!
this is my listener on login viewcontroller
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if authenticationContext.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) && DataContainerSingleton.sharedDataContainer.fingerPrintEnabled == "SI"{
self.touchIdListener()
}
}
with
func touchIdListener(){
authenticationContext.evaluatePolicy(
.deviceOwnerAuthenticationWithBiometrics,
localizedReason: self.valFromCurrentLanguaje(valor: "LOGIN_FINGER_MSG"),
reply: { [unowned self] (success, error) -> Void in
if( success ) {
let keychain = KeychainSwift()
let data = keychain.get(Constants.USER_KEY)?.components(separatedBy: ",")
DispatchQueue.main.async {
self.showProgress(text: Constants.EMPTY_STRING)
}
self.fromTouchId = true
self.loginBL.startLogin(email: (data?[0])!, password: data?[1])
}else {
// Check if there is an error
if let error = error {
print("\(error.localizedDescription)")
}
}
})
}
So the solution was change the dismiss
self.dismiss(animated: true, completion: nil)
for a new instance
var storyboard = UIStoryboard()
let vc : LoginViewController
if (Constants.IS_IPAD) {
storyboard = UIStoryboard.init(name: "LoginIpad", bundle: nil)
vc = storyboard.instantiateViewController(withIdentifier: "ipadViewController") as! LoginViewController
} else {
storyboard = UIStoryboard.init(name: "Login", bundle: nil)
vc = storyboard.instantiateViewController(withIdentifier: "iphoneViewController") as! LoginViewController
}
let navigationController = UINavigationController(rootViewController: vc)
self.present(navigationController, animated: true, completion: nil)

3D touch to UITabView

I am using a tabViewController and want to know how I can make a 3D touch action from the home screen bring up a tab. I already have the code but can't seem to get a specific tab to show up; I can only get a window. My AppDelagate.swift is below. Any help?
enum ShortcutIdentifier: String
{
case First
case Second
init?(fullType: String)
{
guard let last = fullType.componentsSeparatedByString(".").last else {return nil}
self.init(rawValue: last)
}
var type: String
{
return NSBundle.mainBundle().bundleIdentifier! + ".\(self.rawValue)"
}
}
func handleShortcutItem(shortcutItem: UIApplicationShortcutItem) -> Bool
{
var handled = false
guard ShortcutIdentifier(fullType: shortcutItem.type) != nil else {return false}
guard let shortcutType = shortcutItem.type as String? else {return false}
switch (shortcutType)
{
case ShortcutIdentifier.First.type:
handled = true
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let navVC = storyboard.instantiateViewControllerWithIdentifier("sourcesview") as! UINavigationController
if let tabBarController = navVC.topViewController as? UITabBarController {
tabBarController.selectedIndex = 4
}
self.window?.rootViewController?.presentViewController(navVC, animated: true, completion: nil)
break
case ShortcutIdentifier.Second.type:
handled = true
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let navVC = storyboard.instantiateViewControllerWithIdentifier("searchview") as! UINavigationController
self.window?.rootViewController?.presentViewController(navVC, animated: true, completion: nil)
break
default:
break
}
return handled
}
You have to set the selectedTab property on your UITabBarController. I assume that the UINavigationController that you load from the nib contains a UITabBarController as top view controller, so after loading the navigation controller from the nib you have to access the tab bar controller and set the selected tab property to the desired tab.
switch (shortcutType)
{
case ShortcutIdentifier.First.type:
handled = true
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let navVC = storyboard.instantiateViewControllerWithIdentifier("sourcesview") as! UINavigationController
if let tabBarController = navVC.topViewController as? UITabBarController {
tabBarController.selectedIndex = 1
}
self.window?.rootViewController?.presentViewController(navVC, animated: true, completion: nil)
break
...
}

Resources