I am having a strange issue. I am trying to pass an object from ViewControllerA to CreateInvitationViewController.
In ViewControllerA I have following code:
func btnPassedRequestTouched(sender:UIButton!)
{
print("button passed request touched")
// pass request
self.performSegueWithIdentifier("createInvitationSegue", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if segue.identifier == "createInvitationSegue" {
let createInvitationView = segue.destinationViewController as! CreateInvitationViewController
let invitation = invitations[self.carousel.currentItemIndex]
createInvitationView.invitation = invitation
}
}
I put a breakpoint on this line: createInvitationView.invitation = invitation, and I can see that this object exists.
In ViewControllerB I have the following code:
class CreateInvitationViewController: UIViewController {
var invitation = Invitation()
override func viewDidLoad() {
super.viewDidLoad()
// if invitation is set, then use it to populate fields
if let _ = self.invitation.id {
invitationText.hidden = false
invitationText.text = self.invitation.note
}
}
I am using Show action on the segue that I made and it looks like this:
This is the error that I am getting:
Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<MyProject.CreateInvitationViewController 0x156365810> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key postRequest.'
Do you have some suggestion why this happens?
It's telling you it cannot find postRequest. That means that you either have some code that is trying to set postRequest or, more likely, you have some control in your storyboard that is trying to connect to an outlet called postRequest, but no such outlet exists (e.g. maybe you had some outlet with that name in the past, removed the outlet from the code, but neglected to update the storyboard accordingly).
Related
I have a push segue on my StoryBoard which is named toGuestVC.
I use that to segue to the next ViewController in my didSelectRowAtIndexPath method like so:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let username = followUsernameArray[indexPath.row]
performSegue(withIdentifier: SG_TO_GUEST_VIEW_CONTROLLER, sender: username)
}
Then in my prepareForSegue:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == SG_TO_GUEST_VIEW_CONTROLLER {
if let nextVC = segue.destination as? GuestCollectionVC, let sender = sender as? String {
print("PRINTING NEXT VC: \(nextVC)") //This prints out the memory address. Not sure if this is what you meant by print nextVC.
nextVC.guestUser = sender
}
}
}
For some reason this line in my prepareForSegue is not running:
nextVC.guestUser = sender.username
When I try to print out the value guestUser in my nextViewController the value of guestUser is nil. But when I print out the value of sender in my prepareForSegue method it is not nil.
So is my sender value not being passed to the next ViewController? I can't find a solution to this problem any ideas?
GuestCollectionVC Implementation:
import UIKit
import Parse
private let reuseIdentifier = "Cell"
class GuestCollectionVC: UICollectionViewController {
var guestUser: String!
override func viewDidLoad() {
super.viewDidLoad()
print("PRINTING SELF IN GuestCollectionVC: \(self)")
loadPosts()
}
func loadPosts() {
//Load posts query
let query = PFQuery(className: PF_POSTS_CLASS)
query.limit = postCount
//Getting error here below this comment when I use guestUser since it is nil
query.whereKey(PF_POSTS_USERNAME_COLUMN, equalTo: guestUser)
query.findObjectsInBackground { (result: [PFObject]?, error: Error?) -> Void in
if error == nil {
if let result = result {
self.uuidOfPosts.removeAll(keepingCapacity: false)
self.imageArrayOfPFFIle.removeAll(keepingCapacity: false)
for postObject in result {
if let uuid = postObject[PF_POSTS_UUID_COLUMN] as? String, let pic = postObject[PF_POSTS_PIC_COLUMN] as? PFFile {
self.uuidOfPosts.append(uuid)
self.imageArrayOfPFFIle.append(pic)
}
}
self.collectionView?.reloadData()
}
}else if error != nil {
print("ERROR FROM GUEST COLLECTION VC FROM loadPosts FUNCTION: \(error?.localizedDescription)")
}
}
}
}
So this is my implementation in the GuestViewController. In my loadPosts method where I used the variable guestUser I am getting the error:
fatal error: unexpectedly found nil while unwrapping an Optional value
From console printing
PRINTING NEXT VC: "InstagramClone.GuestCollectionVC: 0x7a6c5cc0"
PRINTING SELF IN GuestCollectionVC: "InstagramClone.GuestCollectionVC: 0x7a6c5100"
it's now obvious that hidden unexpected instance of GuestCollectionVC was created. So, there are different errors occurs depending on order of this two objects invoke their viewDidLoad method (can be any order). Also there are can be other errors in nextVC viewDidLoad method, but this is other story for other question.
You got this problems because you created action segue, that works automatically on cell click (hidden view controller created), and at the same time you are perform this segue in code, creating second controller nextVC.
To solve issue, you should find and remove that segue and add new one, not action segue from some element of your view controller, but "empty" segue between view controllers. To create segue of this type you should select first view controller, hold "control" key and start dragging to next view controller from yellow square on top of first view controller (that symbol controller itself), choose "show", and set identifier.
Since I don't have the full context of the values within your tableView method I can only speculate. That said, the sender you're passing in should be the view controller:
performSegue(withIdentifier: "toGuestVC", sender: username)
You're passing in a value called username which looks to be a string value? It should be something like:
performSegue(withIdentifier: "toGuestVC", sender: self)
where self is your view controller. If you're passing in a string value to sender then in your prepareForSegue method then sender does not have a property called username sender actually is username. Therefore you should pass the value elsewhere:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let indexPath = self.tableView.indexPathForSelectedRow
if let nextVC = segue.destination as? GuestCollectionVC {
nextVC.guestUser = followUsernameArray[indexPath.row]
}
}
I ma getting the following error when trying to assign a value to a variable in the destination for a segue
Thread 1: EXC_BAD_ACCESS(Code1, adderss = some-address)
the code that is causing it is as follow's
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if(testNo < 12){
let letterTestController = segue.destinationViewController as! LetterTestHolderViewController
// CRASHES ON THE NEXT LINE
letterTestController.answer = correctAnswers[testNo]
letterTestController.testAnswers = options[testNo]
letterTestController.testNo = testNo
print("SegueIng")
}
}
It was working fine a while age and i have no idea what is causing this error.
Edit
Debugger variable values
I have a uitableview which is filled with core data objects. I need to pass object for selected row to detail view controller. Following is my code for it:
Alert Screen:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "ShowAlertDetails" {
if let destination = segue.destinationViewController as? AlertDetailsViewController {
if let blogIndex = tblvwAlerts!.indexPathForSelectedRow()?.row {
let objAlert:Alert = arrReferrals[blogIndex] as! Alert
destination.objAlert = objAlert
}
}
}
}
Detail View Controller:
class AlertDetailsViewController: UIViewController {
#IBOutlet weak var tblvwHitDetail: UITableView?
var objAlert:Alert = Alert()
I am getting following error when I am trying to copy object from first page to detail page:
CoreData: error: Failed to call designated initializer on NSManagedObject class 'Alert'
The error is caused by calling Alert() method in var objAlert:Alert = Alert(). You can set Alert as an Implicitly unwrapped value var objAlert:Alert!. It will be initially nil and then it will hold the reference of the managed objected which is passed from the previous controller.
Before I begin, let me say that I have taken a look at a popular post on the matter: Passing Data between View Controllers
My project is on github https://github.com/model3volution/TipMe
I am inside of a UINavigationController, thus using a pushsegue.
I have verified that my IBAction methods are properly linked up and that segue.identifier corresponds to the segue's identifier in the storyboard.
If I take out the prepareForSegue: method then the segue occurs, but obviously without any data updating.
My specific error message is: Could not cast value of type 'TipMe.FacesViewController' (0x10de38) to 'UINavigationController' (0x1892e1c).
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
if segue.identifier == "toFacesVC" {
let navController:UINavigationController = segue.destinationViewController as! UINavigationController
let facesVC = navController.topViewController as! FacesViewController
facesVC.balanceLabel.text = "Balance before tip: $\(balanceDouble)"
}
}
Below is a screenshot with the code and error.
side notes: using Xcode 6.3, Swift 1.2
A couple of things:
1: change your prepareForSegue to
if segue.identifier == "toFacesVC" {
let facesVC = segue.destinationViewController as! FacesViewController
facesVC.text = "Balance before tip: $\(balanceDouble)"
}
2: add a string variable to your FacesViewController
var text:String!
3: change the FacesViewController viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
balanceLabel.text = text
}
The reasons for all the changes: the segue destinationViewController is the actual FacesViewController you transition to -> no need for the navigationController shenanigans. That alone will remove the "case error", but another will occur due to unwrapping a nil value because you try to access the balanceLabel which will not have been set yet. Therefore you need to create a string variable to hold the string you actually want to assign and then assign that text in the viewDidLoad - at the point where the UILabel is actually assigned.
Proof that it works:
4: If you want display two decimal places for the balance you might change the String creation to something like (following https://stackoverflow.com/a/24102844/2442804):
facesVC.text = String(format: "Balance before tip: $%.2f", balanceDouble)
resulting in:
I'm using a prepareForSegue method,
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if segue.identifier == "roundSegue" {
var selectedRound:NSManagedObject = roundList[self.tableView.indexPathForSelectedRow().row] as NSManagedObject
let SVC: SetupVC = segue.destinationViewController as SetupVC
SVC.course = selectedRound.valueForKey("course") as String
SVC.existingRound = selectedRound
}
}
However, it is throwing an error "Thread 1:EXC_BAD_INSTRUCTION", on the 'if segue.identifier == "roundSegue"' line...any thoughts on why it would be throwing this error?
It is possible that your segue identifier is nil. If this is the case, you are attempting to unwrap a implicitly unwrapped optional variable that is nil, which would cause a crash. try this instead:
if let identifier = segue.identifier {
if identifier == "roundSegue" {
// your code here.
}
}
STUPID ME! I had an iboutlet that needed to be deleted. that was it. Thanks for all the help though.
In the Storyboard interface. Click the segue and open the attributes inspector
Set the seque identifier and the bad access should be fixed