unrecognized selector sent to instance in swift - ios

I'm using a segue in code from one view controller to another view controller, they are both embedded in a Navigation Controller, the segue is "Show".
This is how I call the segue:
performSegueWithIdentifier("LogIn", sender: self)
And this is what I do:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "LogIn" {
segue.destinationViewController.setShowsCancelButton(false, animated: false)
}
}
And as soon as the segue is triggered I get an error in Xcode :
[Chooze.LogInOrRegisterViewController setShowsCancelButton:animated:]: unrecognized selector sent to instance 0x7f928b93aed0
2014-09-23 16:40:04.608 Chooze[9935:939290] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Chooze.LogInOrRegisterViewController setShowsCancelButton:animated:]: unrecognized selector sent to instance 0x7f928b93aed0'

Since the destination view controller is embedded in a navigation controller, your code is trying to invoke setShowsCancelButton on the navigation controller. Instead, you should access the navigation controller's topViewController property, and call setShowsCancelButton on the object it returns, for example:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!)
{
if segue.identifier == "Login" {
let navController = segue.destinationViewController as UINavigationController
let controller = navController.topViewController as LoginOrRegisterViewController
controller.setShowsCancelButton(false, animated: false)
}
}

Related

Passing same variable to container view with different value

I have one button on main viewController which has default value nil which is associated by dropDown pod.
On same viewController there is also a container view.
During first time loading, I get the default value of a variable from shared preferences and pass that value to container view by performSegue.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if(segue.identifier == "dataToContainerView"){
DispatchQueue.main.async {
var secondVC = segue.destination as! secondViewController //container viewController
secondVC.variable = self.variable
}
}
}
Now I need to pass the value of same variable again by selecting from dropdown button by user.
dropDown.selectionAction = { [unowned self] (index, item) in
self.button.setTitle(item, for: UIControlState())
self.variable = item
print(item)
self.performSegue(withIdentifier: "dataToContainerView", sender: nil)
//performing segue to resend the new value of the variable.
}
The above code performs properly till print(item).
But I am getting the following error on performSegue.
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'There are unexpected subviews in the container view. Perhaps the embed segue has already fired once or a subview was added programmatically?
How should I pass the value to container view second time overriding first value with the help of dropDown pod?
update:- I need the variable value so that I can pass it to json parser on container viewController. And the code on container viewController re-executes.
You need to save a reference to your embedded controller so that you can update it again later. Do this in the first segue:
// Declare a local variable in your parent container:
var secondVC: secondViewController!
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if(segue.identifier == "dataToContainerView"){
DispatchQueue.main.async {
self.secondVC = segue.destination as! secondViewController
//container viewController
self.secondVC.variable = self.variable
}
}
}
Then later when you need to update the variable you can just reference it directly:
self.secondVC.variable = self.variable
self.secondVC.viewDidLoad()

'NSInvalidArgumentException', reason: 'Receiver has no segue with identifier 'unwind''

when user clicked button
let uvc: UINavigationController =
self.storyboard?.instantiateViewController(withIdentifier: "nationSelect") as! UINavigationController
uvc.modalTransitionStyle = UIModalTransitionStyle.coverVertical
self.present(uvc, animated: true, completion: nil)
run this code.
identifier:nationSelect storyboard img
cell, closebutton, VC segue unwind img
and
button vc have this function
#IBAction func unwindFromPostCodeSelectionView(_ sender: UIStoryboardSegue) {
print("unwindFromPostCodeSelectionView")
}
and nationSelect VC
when collectionview's cell clicked
run this code
performSegue(withIdentifier: unwind, sender: nil)
and prepare function
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let identifier = segue.identifier, identifier == unwind else{
return
}
guard let vc = segue.destination as? CurationRequestViewController else {
return
}
vc.getAddress.setTitle( (continent.text ?? " ") + " " + nation , for: .normal)
}
but i got this error
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Receiver () has no segue with identifier 'unwind''
help me plz!!!
Looks like you are trying to implement unwind segue and you missed to specify the identifier for unwind segue.
Here are the steps to properly implement unwind segue:
Step 1: If you are trying to implement unwind segue from Vc2 to Vc1 (Coming back to VC1 from VC2) then in VC1 add the IBAction as
#IBAction func unwindToViewController1(segue : UIStoryboardSegue) {
//you will get control back here when you unwind
}
Step 2:
Open storyboard, select VC2 and control drag from ViewController to Exit option in storyboard as shown below
This should show a popover and the method you just declared select it.
Step 3: (Step I think you missed)
Select the unwind segue you just added and provide a identifier to it.
Step 4:
Now whenever you wanna return back to VC1 you can simply call
self.performSegue(withIdentifier: "unwindSegueToViewController1", sender: nil)
Hope it helps :) Happy coding

Passing data via segue and sqlite

I am trying to pass some data from selected row via segue to another viewcontroller but I cannot. I tried almost everything, but I always get:
2016-06-16 18:41:20.069 Wine Dictionary[3282:55647] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Receiver (<Wine_Dictionary.DetailUI: 0x7f8a1ae2fa60>) has no segue with identifier 'SegueToDetailUI''
I already tried changing method, changing identifier etc.
Here is the screenshot of the code: http://prntscr.com/bh6e6l
Here is the screenshot of the storyboard and segue identifier: http://prntscr.com/bh6f6q
delete your code in didSelectRowAtIndexPath and add this
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if (segue.identifier == "SegueToDetailUI") {
let selectedInfo = self.NAME?[indexPath.row]
let indexPath = tableView.indexPathForSelectedRow
let destinationVC = segue.destinationViewController as! DetailUI
destinationVC.programVar = selectedInfo!
}
}
assuming I spelled everything correctly (if not just correct my spelling)
Try deleting your segue and recreate it..
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "SegueToDetailUI")
{
if let rowselect = tableView!.indexPathForSelectedRow
{
let selectedInfo =self.NAME?[rowselect]
let moveVC:DetailUI = segue.destinationViewController as! DetailUI
moveVC.programVar = selectedInfo!
}
}
}
Since your segue goes from MainUI to DetailUI, performSegueWithIdentifier("SegueToDetailUI") musts be run from MainUI, the view controller at the origin of the segue.
Invoking this method will instantiate the DetailUI view controller, and push it on the screen.
Configuration of the newly created DetailUI view controller happens in the method MainUI.prepareForSegue. That's where you'll provide the programVar property.
Remember: when you use storyboards, you never never never instantiate view controllers yourself (let vc = MyViewController()). Instead, you'll always use one of the NSStoryboard.instantiateViewController... methods, or NSViewController.performSegue(...).

Swift - Unwind Segue triggering error

I am using for the first time the Unwind Segue approach. I have multiple view controllers as can be seen in the picture below (a few of them shown of course). In the Edit Profile I have a Done button. Once clicked I trigger an IBAction that triggers an unwind segue.
Here is the code for the Done button in the nav bar:
#IBAction func unwindToMainViews(sender: UIStoryboardSegue) {
//let sourceViewController = sender.sourceViewController
self.performSegueWithIdentifier("unwindToMainSegue", sender: self)
}
and in the
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!)
I am doing the following to pass data from Edit Profile back to Home View
if (segue.identifier == "unwindToMainSegue") {
// pass data to next view
let tabCtrl = segue.destinationViewController as! UITabBarController
let destinationVC = tabCtrl.viewControllers![0] as! HomeViewController
destinationVC.userObject = self.userObject;
}
When segue identifier is matched and code is executed (to transfer userObject from this controller to another), it triggers the error:
Could not cast value of type 'app.EditProfileViewController' (0x100b99d80) to 'UITabBarController' (0x104a1d030).
How can this error be fixed? I am surprised since i am casting to UITabBarController so thought it should work.
You don't return to the UITabBarController in an unwind segue. You return to the ViewController that triggered the original segue, or one if its ancestors.
As #jlehr stated in the comments:
Unwind segues don't return to anything; they dismiss any pushed and
presented view controllers between the source and destination view
controller. The destination is wherever the implementation of the
unwind method is found, regardless of how the source view controller
was presented.
To unwind to the viewController that triggered the original segue, you need to implement the #IBAction func returnToHere(segue: UIStoryboardSegue) function in the viewController you want to return to.
Then when you set up your Done button by dragging to the Exit icon, you select returnToHere from the pop-up.
To pass data back to the sourceViewController, give your unwind segue an identifier such as "unwindToSource", then override prepareForSegue in the viewController you are returning from:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "unwindToSource" {
let dvc = segue.destinationViewController as! SourceViewController
dvc.userObject = self.userObject
}
}

class data becomes nill when I reference it in my 'prepareForSegue' method

I have a tableview with buttons each containing a tag (according to indexPath.row), and when I press a particular button the details of the contents of that cell (which relates to a class called EventEntity) is meant to be passed through a 'prepareForSegue' method to another screen.
The value is assigned in the 'infoButtonDidPress' method as shown below:
func infoButtonDidPress(sender: UIButton){
eventPressed = eventEntities[sender.tag]
println (eventPressed.name) // prints the name, all good here.
}
The problem is that when I assign the contents of eventPressed to the destinationVC in 'prepareForSegue', they are nil. Code below:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "infoButtonSegue"){
var svc = segue.destinationViewController as! EventDetailsViewController;
println (eventPressed.name) // NOPE.
svc.name = eventPressed.name //also NOPE!
}
eventPressed is declared above viewDidLoad:
var eventPressed: EventEntity! = EventEntity()
The error I get when I try either of those lines with the 'NOPE' comment is 'Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Appname.EventEntity name]: unrecognized selector sent to instance 0x7fa280e16a50' error
Whats going on here?
Thanks in advance!
UPDATE
I have moved performWithSegue to the infoButtonDidPress method, but I am now unable to reference the destinationViewController.
My infoButtonDidPress now looks like this:
func infoButtonDidPress(sender: UIButton){
let eventPressed = eventEntities[sender.tag]
var destinationViewController: UIViewController = self.destinationViewController as EventDetailsViewController
// error: the current VC does not have a member named destinationViewController
self.performSegueWithIdentifier("infoButtonSegue", sender: self)
}
As you discovered, prepareForSegue is happening before infoButtonDidPress is called.
To fix this, instead of wiring the segue from the prototype cell in your tableView, wire it from the viewController icon at the top.
See this: How to wire segue from ViewController icon
Make sure to set the identifier to "infoButtonSegue". Then call the segue from infoButtonDidPress after you have set the value for eventPressed:
func infoButtonDidPress(sender: UIButton){
eventPressed = eventEntities[sender.tag]
self.performSegueWithIdentifier("infoButtonSegue", sender: self)
}
And then, in prepareForSegue pass the value to the destination view controller:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "infoButtonSegue") {
let dvc = segue.destinationViewController as! EventDetailsViewController
dvc.name = eventPressed.name
}
}

Resources