I have this strange crash in Crashlytics report and I'm not sure what's going on. I don't even know what does the line number "0" means. Any ideas?
Code from didSelect method:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
switch indexPath.section {
case 1:
let vc = WTShowDetailVC()
vc.show = bottomFeaturedShows[indexPath.row].show
navigationController?.pushViewController(vc, animated: true)
case 2:
let vc = WTShowDetailVC()
vc.show = lastWatchedShows[indexPath.row]
navigationController?.pushViewController(vc, animated: true)
case 3:
let vc = WTTapperProfileUserVC()
vc.tapper = popularTappers[indexPath.row]
navigationController?.pushViewController(vc, animated: true)
default:
println("Something went wrong")
}
}
This normally happens when you are unwrapping an optional and it's value is nil. Try putting a nil check to navigationController.
if let navigationcontroller: UINavigationController = navigationController {
navigationcontroller.pushViewController(vc, animated: true)
}
Related
I am presenting views from a switch statement as seen in the code. What code would i add to present each view in full screen. I have tried a few methods with self, but nothing changes. I have also tried setting the screen from auto to full screen in storyboard. Any ideas??
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let settingsSection = SettingsSection(rawValue: indexPath.section)
switch settingsSection {
case .social:
let value = SocialOptions(rawValue: indexPath.row)
switch value {
case .editProfile:
present(editProfileVC, animated: true) {
}
case .changePassword:
present(changePasswordVC, animated: true) {
}
case .deleteAccount:
present(deleteVC, animated: true) {
}
default:
debugPrint("Invalid Selection")
}
case .communications:
let value = CommunicationOptions(rawValue: indexPath.row)
switch value {
case .notifications:
present(notificationVC, animated: true) {
}
case .language:
present(languageVC, animated: true) {
}
case .contactUs:
present(contactVC, animated: true) {
}
default:
debugPrint("Invalid selection")
}
default:
debugPrint("Invalid selection")
}
}
}
Embed your ViewControllers in a UINavigationController. You can set UINavigationController().navigationBar.isHidden = true if you don't want the nav bar at the top. The code you want is UIViewController().modalPresentationStyle = .fullScreen.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let settingsSection = SettingsSection(rawValue: indexPath.section)
var vc: UIViewController?
var navController: UINavigationController!
switch settingsSection {
case .social:
let value = SocialOptions(rawValue: indexPath.row)
switch value {
case .editProfile: vc = editProfileVC
case .changePassword: vc = changePasswordVC
case .deleteAccount: vc = deleteVC
default: debugPrint("Invalid Selection")
}
case .communications:
let value = CommunicationOptions(rawValue: indexPath.row)
switch value {
case .notifications: vc = notificationVC
case .language: vc = languageVC
case .contactUs: vc = contactVC
default: debugPrint("Invalid selection")
}
default: debugPrint("Invalid selection")
}
if let vc = vc {
navController = UINavigationController(rootViewController: vc)
navController.modalPresentationStyle = .fullScreen
self.present(navController, animated: true)
}
}
How can I make the VC appear also
I tried this but ms loaded clean without buttons and TextView.
let modalViewController = ClipboardViewController()
modalViewController.modalPresentationStyle = .overCurrentContext
present(modalViewController, animated: true, completion: nil)
Example:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.row == 0 {
self.navigationController!.pushViewController(self.storyboard!.instantiateViewController(withIdentifier: "ViewController") as UIViewController, animated: true)
} else if indexPath.row == 1 {
// VC with animation
} else if indexPath.row == 2 {
self.navigationController!.pushViewController(self.storyboard!.instantiateViewController(withIdentifier: "Favorite") as UIViewController, animated: true)
} else if indexPath.row == 3 {
self.navigationController!.pushViewController(self.storyboard!.instantiateViewController(withIdentifier: "Settings") as UIViewController, animated: true)
}
}
let modalViewController = self.storyboard?.instantiateViewController(withIdentifier: "ClipboardViewController ID") as? ClipboardViewController
modalViewController?.modalPresentationStyle = .overCurrentContext
self.present(modalViewController!, animated: true, completion: nil)
I am generating table cell.
cell2 = settingsTableView.dequeueReusableCell(withIdentifier: "ModuleCell", for: indexPath) as! ModuleCell
It looks fine, the cell has tag = 2000.
In override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath), I am checking the tag end if tag == 2000 I want to present modal view. I am doing that in this way
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let modalView = storyboard.instantiateViewController(withIdentifier: "ModalView")
present(modalView, animated: true, completion: nil)
Then in modalView I have a button which should dismiss modalView, what's happening as expected.
#IBAction func saveAndClosePopup(_ sender: UIButton) {
UserDefaults.standard.removeObject(forKey: "ActiveCantachoOptions")
UserDefaults.standard.set(Modules.activeCantachoOptions, forKey: "ActiveCantachoOptions")
self.dismiss(animated: true, completion: nil)
}
However, when I want to immediately present modalView again, sometimes it's okay, but sometimes I need to hit two times on the cell, which should show modalView. After the first hit, there is no difference if I hit the cell again in 1 second or in 30 seconds. The modalView will appear after the second one. What is the cause?
Try this
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let modalView = storyboard.instantiateViewController(withIdentifier: "ModalView")
self.present(modalView, animated: true) {
tableView.deselectRow(at: indexPath, animated: false)
}
}
I have as a Menu tableview in my custom navigation bar. If i click on one cell , it should take me to another view controller. But my app crashes when i click on it.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return menu_items.count //It has 5 values
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.value1, reuseIdentifier: "cell")
cell.textLabel?.text = menu_items[indexPath.row]
cell.textLabel?.textColor = .white
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let item = menu_items[indexPath.row]
if (item == "Patienten") {
tableView.removeFromSuperview()
let vc = self.storyboard?.instantiateViewController(withIdentifier: "patientView") as! patientViewVC //App crashes here
self.present(vc, animated: false, completion: nil)
} else if (item == "Mitarbeiter") {
} else if (item == "Kalender") {
} else if (item == "Tourenplanung") {
tableView.removeFromSuperview()
let vc = storyboard?.instantiateViewController(withIdentifier: "tour") as! tourVC //App crashes here
self.present(vc, animated: false, completion: nil)
}else if (item == "Abmelden") {
let vc = self.storyboard?.instantiateViewController(withIdentifier: "loginvc") as! LoginVC //App crashes here
self.present(vc, animated: false, completion: nil)
}
let selectedCell:UITableViewCell = tableView.cellForRow(at: indexPath)!
selectedCell.contentView.backgroundColor = colorLightGreen
}
}
I have many times verified all Identifier names and view controller names are correct.
Make sure you load a correct storyboard before instantiating the viewController.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let item = menu_items[indexPath.row]
if (item == "Patienten") {
tableView.removeFromSuperview()
let storyBoard = UIStoryboard(name: "StoryboardName", bundle: nil)
let vc = storyBoard.instantiateViewController(withIdentifier: "patientView") as! patientViewVC
self.present(vc, animated: false, completion: nil)
} else if (item == "Mitarbeiter") {
} else if (item == "Kalender") {
} else if (item == "Tourenplanung") {
tableView.removeFromSuperview()
let storyBoard = UIStoryboard(name: "StoryboardName", bundle: nil)
let vc = storyBoard.instantiateViewController(withIdentifier: "tour") as! tourVC //App crashes here
self.present(vc, animated: false, completion: nil)
}else if (item == "Abmelden") {
let storyBoard = UIStoryboard(name: "StoryboardName", bundle: nil)
let vc = storyBoard.instantiateViewController(withIdentifier: "loginvc") as! LoginVC //App crashes here
self.present(vc, animated: false, completion: nil)
}
let selectedCell:UITableViewCell = tableView.cellForRow(at: indexPath)!
selectedCell.contentView.backgroundColor = colorLightGreen
}
StoryboardName above is the name of the storyboard that contains the patientViewVC, tourVC, LoginVC
A view controller in storyboard needs to have a custom class set in Identity inspector:
Then you can cast it to desired type. If all the view controllers are in the same storyboard, you can instantiate them with storyboard property of self. If they are in different storyboard, you have to instantiate UIStoryboard instance with corresponding name and use it.
Btw, why are you calling tableView.removeFromSuperview() after cell selection?
I have a few viewcontrollers in storyboard with certain identifiers and when I try to access them like this:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let mainViewController = sideMenuController!
let vcName = identities[indexPath.row]
let viewController: UIViewController! = storyboard?.instantiateViewController(withIdentifier: vcName)
let navigationController = mainViewController.rootViewController as! NavigationController
navigationController.pushViewController(viewController, animated: true)
mainViewController.hideLeftView(animated: true, completionHandler: nil)
}
The app crashes. This line is detecting that the value is nil. Can anyone explain how this is nil while unwrapping?
navigationController.pushViewController(viewController, animated: true)
After several attempts I managed to get rid off the fatal error. However the view controller still does not appear upon tapping on the table view item.
Original Project -
link
Edited Project -
link
Well, the project is a little "messed up" :-)
First: You need to somehow get "the" UINavigationController (or derived class).
Since your LeftViewController is not on the navigation stack, it does not have a navigationController set. So, you need to get it from the mainViewController:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
print(storyboard)
let mainViewController = sideMenuController!
let vcName = identities[indexPath.row]
let viewController: UIViewController! = storyboard.instantiateViewController(withIdentifier: vcName)
print(viewController)
if let theNavigationController = mainViewController.rootViewController as? UINavigationController {
print("Gotcha")
theNavigationController.pushViewController(viewController!, animated: true)
mainViewController.hideLeftView(animated: true, completionHandler: nil)
}
}
Second, there is still a problem:
The view controller with identifier 'A' is of type EngineTunningParamteres, derived from UINavigationController. You cannot push a navigation controller onto an existing navigation controller. Therefore, we have to change the class, too:
class EngineTunningParamteres: UIViewController {
override func viewDidLoad() {
print("hi") }
}
Now it works. You're welcome.
let viewController: UIViewController!
is an Optional, with this ! you are just telling the compiler "I know this may be nil but don't worry, at run time it will never be nil".
If you want to get rid of this Optional you have to unwrap the storyboard :
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let mainViewController = sideMenuController!
let vcName = identities[indexPath.row]
let viewController = storyboard!.instantiateViewController(withIdentifier: vcName)
let navigationController = mainViewController.rootViewController as! NavigationController
navigationController.pushViewController(viewController, animated: true)
mainViewController.hideLeftView(animated: true, completionHandler: nil)
}