Passing data via segue and sqlite - ios

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(...).

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()

Updating TableView within containerview

I have my UIViewController, which is a person's profile page, it displays their name and picture. Within that UIViewController I have a UIContainerView that displays a static UITableView. I'm having a little trouble updating the cells of the table when the profile page loads. Here's my storyboard:
I have tried the following, within my UIViewController.
I created an outlet to my UIView and passed the person object to it.
In my UIView I called the segue to pass the object to the UITableViewController and from there I was going to update some labels.
func prepareForSegue(segue: UIStoryboardSegue!, sender: Any?){
if segue.identifier == "containerSegue"{
let statsTable = segue.destination as! CollectionTableViewController
statsTable.currentPerson = currentPerson
}
}
My Segue is never called though. I have moved it to the main UIViewController in case it should be called from there, but again not called. What am I doing wrong with this approach?
Assuming you have set the Segue Identifier to "containerSegue" you should get it in your "Stats" view controller.
Are you using Swift 3? It's possible you just have the func definition wrong:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "containerSegue" {
let statsTable = segue.destination as! CollectionTableViewController
statsTable.currentPerson = currentPerson
}
}
That should work.

Accessing Container view controller from parent controller in Swift 2

I want to access label of container view controller from parent view controller. I have tried the following:
prepareForSegue is a function in parent view controller.
ViewController2 is the container view controller.
parin2 is the name of the label in the container view controller.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!)
{
let vc1 = segue.destinationViewController as! ViewController2;
vc1.parin2.text=String("helo");
}
This gives the following error:
fatal error: unexpectedly found nil while unwrapping an Optional value
You didn't say exactly which line caused the error, but my guess is that it was let vc1 = segue.destinationViewController as! ViewController2 (by the way, please omit the ';'s in Swift). The as! appears to be failing because the destination view controller isn't a ViewController2. To verify this, set a breakpoint on that line, then examine the segue's destinationViewController property to see what kind of view controller it is. If it's not a ViewController2, then the problem is in your storyboard. Either you're getting a segue that you didn't expect, or the class of the destination in the storyboard isn't a ViewController2.
A better pattern for handling prepareForSegue is the following:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
// ALWAYS check the segue identifier first! If you forgot to put one on
// your segue in the storyboard, then you should see a compiler warning.
switch segue.identifier {
case "SegueToViewController2":
guard let destination = segue.destinationViewController as? ViewController2 else {
// handle the error somehow
return
}
default:
// What happens when the segue's identifier doesn't match any of the
// ones that you expected?
}
}

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
}
}

Could not cast value of type 'UITableViewController' to 'UINavigationController'

I'm trying to segue from one view controller to another, and pass data to the next controller. But I keep getting this error:
Could not cast value of type 'UITableViewController' to 'UINavigationController'
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "segueLogWaterData") {
// pass data to next view
let nav = segue.destinationViewController as! UINavigationController
let segueViewController = nav.topViewController as! WaterDataViewController
}
}
This happens with WaterDataViewController as a UITableViewController. I've also tried embedding WaterDataViewController into a UINavigationController but I get a similar error:
Could not cast value of type 'UITableViewController' to 'MyApp.WaterDataViewController'
What am I doing wrong?
Actually, the segue.destinationViewController isn't the navigation controller; rather, it is the view controller that the segue is opening. Since UITableViewController is a subclass of UIViewController, this code should work just fine:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "segueLogWaterData") {
let dest = segue.destinationViewController as! WaterDataViewController
//Assign to dest's properties
}
}
nav.topViewController is a UITableViewController. Apparently, WaterDataViewController is not a subclass of UITableViewController.
Do you mean to be using rootViewController instead?
I get the same error sometimes because of "omitting class" to my view controller in the storyboard.

Resources