Passing the Object from one ViewController to another - ios

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "shoesDetails" {
let indexPath = self.table.indexPathForSelectedRow()
let shoesCon:ShoesTableControler = segue.destinationViewController as! ShoesTableControler
let shoesCategories:RepoSitory = arrofRepository[indexPath!.row]
shoesCon.object = shoesCategories
}
}
class ShoesTableControler: UIViewController {
var object = [ProductShoes]()
}
class ProductShoes {
var product_id : String
var product_name : String
init(json :NSDictionary) {
self.product_id = json["product_id"] as! String
self.product_name = json["product_name"] as! String
}
class RepoSitory {
var name : String
var ids : String
init(json :NSDictionary) {
self.name = json["category_name"] as! String
self.ids = json["id"] as! String
}
}
I have 3 classes in firstViewController. We show the data it's done. After that, when user click on specific cell, then show the data. Now I have created the ShoesTableController and in ShoesTableController we create the Product Class obj. I want to access this. The problem is in this line in Objective C. I am doing this and it is working perfect but in swift it does know what happened:
shoesCon.object = shoesCategories

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if segue.identifier == "shoesDetails" {
let indexPath = self.table.indexPathForSelectedRow()
let shoesCon:ShoesTableControler = segue.destinationViewController as! ShoesTableControler
let shoesCategories:RepoSitory = arrofRepository[indexPath!.row]
shoesCon.object = shoesCategories
}
}
class ShoesTableControler: UIViewController {
var object : RepoSitory?
its solve my problem i have my own mistake sorry for posting this question

Related

Segue using tableViewCells

I am going to try to be as clear as I can be on this question but if you need more information please please ask. I have a tableviewcontroller that has a list of all the messages the logged in user has had with other users of the app. When clicked the logged in user clicks a cell, I would like for the user to segue to a view controller that allows them to chat with whatever user they like. This chat was acquired using JSQMessageController. However, when I set it the segue in the tableviewcontroller, show below:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let message = messages[indexPath.row]
if message.ReceiverId != self.loggedInUserUid {
var newVariable = message.ReceiverId
if self.userpicuid == newVariable {
let ref = FIRDatabase.database().reference().child("users").child(userpicuid!)
ref.observeSingleEvent(of: .value, with: { (snapshot)
in
if let dictionary = snapshot.value as? [String: AnyObject]{
for post in dictionary {
let messages = post.value as! [String: AnyObject]
for (id, value) in messages {
self.username = messages["username"] as? String
}}}})}} else if message.senderId != self.loggedInUserUid {
let newVariable = message.senderId
if self.userpicuid == newVariable {
let ref = FIRDatabase.database().reference().child("users").child(userpicuid!)
ref.observeSingleEvent(of: .value, with: { (snapshot)
in
if let dictionary = snapshot.value as? [String: AnyObject]{
for post in dictionary {
let messages = post.value as! [String: AnyObject]
for (id, value) in messages {
self.username = messages["username"] as? String
}}}})}
}
performSegue(withIdentifier: "MessageNow", sender: self.userpicuid)
}
override public func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard segue.identifier == "MessageNow", let chatVc = segue.destination as? SendMessageViewController else {
return
}
chatVc.senderId = self.loggedInUser?.uid
chatVc.receiverData = sender as AnyObject
chatVc.senderDisplayName = self.userpicuid
chatVc.username = self.username
}
I get an error in the MessageViewController:
var receiverData: AnyObject?
override func viewDidLoad() {
super.viewDidLoad()
let receiverId = receiverData as! String
let receiverIdFive = String(receiverId.characters.prefix(5))
let senderIdFive = String(senderId.characters.prefix(5))
if (senderIdFive > receiverIdFive)
{
self.convoId = senderIdFive + receiverIdFive
}
else
{
self.convoId = receiverIdFive + senderIdFive
}}
I get the error on the let receiverId = receiverData as! String that:
Could not cast value of type 'Chat_App.MessageTableViewCell' (0x10eb2ef10) to 'NSString' (0x110ab1c60).
in a different view controller, I have:
#IBAction func sendMessage(_ sender: Any) {
performSegue(withIdentifier: "sendMessageToUser", sender: self.userpicuid)
}
override public func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard segue.identifier == "sendMessageToUser", let chatVc = segue.destination as? SendMessageViewController else {
return
}
chatVc.senderId = self.loggedInUser?.uid
chatVc.receiverData = sender as! String!
chatVc.senderDisplayName = self.userpicuid
chatVc.username = self.username
}
And it segues perfectly.
Sender is Any? and you're casting it to AnyObject. AnyObject refers to a class type, and it's asserting when you attempt to cast it to a Swift value type (String).
Try this instead:
chatVc.receiverData = NSString(string: sender as! String)
Your sender is the the UITableViewCell that initiated the segue. You are crashing when casting it to NSString. Remove this line
let receiverId = receiverData as! String
In prepareForSegue do this instead
chatVc.receiverData = self.userpicuid

My Array Restarts and Not Append

class NewCourseViewController: UIViewController {
#IBOutlet weak var courseNameTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
if segue.identifier == "newClassComplete" {
if let vcSendingToo = segue.destination as? CoursesTableViewController {
// Pass courseName to nameOfCourses Array
// Course Name
let courseName = courseNameTextField.text!
vcSendingToo.nameOfCourse = courseName
vcSendingToo.nameOfCourses.append(vcSendingToo.nameOfCourse)
}
class CoursesTableViewController: UITableViewController {
var nameOfCourses = [String]()
var nameOfCourse = ""
}
It restarts to a blank array rather than add a value to the same array. I can't find any examples that are online that'll help resolve my issue. It was working fin then stopped all of a su
Have you tried to change this line
let courseName = courseNameTextField.text!
vcSendingToo.nameOfCourse = courseName
vcSendingToo.nameOfCourses.append(vcSendingToo.nameOfCourse)
to this?
let courseName = courseNameTextField.text ?? "" //validate for nil
vcSendingToo.nameOfCourse = courseName
vcSendingToo.nameOfCourses = [courseName]
I made the variables global and removed the "vcSendingToo" properties.

Retrieving firebase data of a tableview cell to a view controller's label

I have like a social app with a sort of newsfeed. if u click on the users name from a post in the newsfeed, you will go to his profile. Now i can't retrieve the data from that specific cell/post to the other viewController.
so i have to display the user's profile, with he's username, etc. but that doesn't work?
i have a Post model:
class Post {
private var _postDescription: String!
private var _profileImageURL: String?
private var _likes: Int!
private var _username: String!
private var _postKey: String!
private var _timeStamp: String!
private var _postRef: Firebase!
var postDescription: String? {
return _postDescription
}
var likes: Int {
return _likes
}
var username: String {
return _username
}
var postKey: String {
return _postKey
}
var profileImageURL: String? {
return _profileImageURL
}
init(description: String, username: String, profileImageURL: String?) {
self._postDescription = description
self._username = username
self._profileImageURL = profileImageURL
}
init(postKey: String, dictionary: Dictionary<String, AnyObject>) {
self._postKey = postKey
if let likes = dictionary["likes"] as? Int {
self._likes = likes
}
if let desc = dictionary ["description"] as? String {
self._postDescription = desc
}
if let imgUrl = dictionary["profileImg"] as? String {
self._profileImageURL = imgUrl
}
if let user = dictionary ["username"] as? String {
self._username = user
} else {
self._username = ""
}
self._postRef = DataService.ds.REF_POST.childByAppendingPath(self._postKey)
}
}
this is my profileVC:
class ProfileVC: UIViewController {
#IBOutlet weak var username: UILabel!
var post: Post?
override func viewDidLoad() {
super.viewDidLoad()
username.text = post.username // gives me a nil error.
}
}
and i use a TapGestureRecognizer in my tableViewCell to perform the segue.
in my cellForRowAtIndexPath:
let profileLblTapRecognizer = UITapGestureRecognizer(target: self, action: #selector(NewsVC.goToProfileScreen(_:)))
profileLblTapRecognizer.numberOfTapsRequired = 1
profileLblTapRecognizer.delegate = self
cell.usernameLabel.tag = indexPath.row
cell.usernameLabel.userInteractionEnabled = true
cell.usernameLabel.addGestureRecognizer(profileLblTapRecognizer)
and the goToProfileScreen function:
func goToProfileScreen(gesture: UITapGestureRecognizer) {
self.performSegueWithIdentifier("ProfileScreen", sender: self)
}
this is my datamodel on firebase:
UPDATE:
i tried this instead:
let profileLblTapRecognizer = UITapGestureRecognizer(target: self, action: #selector(NewsVC.prepareForSegue(_:sender:)))
with this function:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "ProfileScreen" {
if let cell = sender as? NewsCell, row = tableView.indexPathForCell(cell)?.row, vc = segue.destinationViewController as? ProfileVC {
vc.post = posts[row]
}
}
}
but that gave me an error on appDelegate: Thread 1: EXC_BAD_ACCESS(code=1, address = 0x1)
I've added this as an answer rather than a comment so that I can add and format some code examples.
When you call performSegueWithIdentifier, a NEW instance of the view controller identified by that segue is created, so all of its properties will be their defaults.
You have two ways of instantiating this view controller and setting properties before it loads. The first is the prepareForSegue option, in your case it may look something like this:
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if (segue.identifier == "ProfileScreen") {
let vc = segue.destinationViewController as! ProfileVC
vc.post = post
}
}
Another option is to create and present the view controller yourself, this example uses a storyboardID
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
let vc = mainStoryboard.instantiateViewControllerWithIdentifier("profileVC") as! ProfileVC
vc.post = post
presentViewController(vc, animated: false, completion: nil)
Update:
I'm not sure why you are adding a tap gesture recogniser to this, you could just use didSelectRowAtIndexPath, have a look at this other question and answer
you could have a property on your table view controller called selectedItem or something similar. and then in didSelectRowAtIndexPath set selectedItem to the item at the current index. Then in prepare for segue you would just do vc.post = selectedItem
Update Two:
After the op sharing their code privately, I noticed that the issue is that the user is using tapGestureRecogniser in the tableView. I added some code into the called function to get the row in which contained the tapped view, once I had the indexPath it was then easy to store it in a temporary property and retreive later in the prepareForSegue method, details below
// temp property
var selectedPost:Post?
// function called on tap
func viewProfile(sender:UITapGestureRecognizer) {
if (sender.state == UIGestureRecognizerState.Ended) {
let point = sender.locationInView(self.tableView)
if let indexPath = self.tableView.indexPathForRowAtPoint(point) {
selectedPost = self.posts[indexPath.row]
performSegueWithIdentifier("ProfileScreen", sender: self)
}
}
}
// Prepare for segue
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "ProfileScreen") {
let vc = segue.destinationViewController as! ProfileVC
if let post = selectedPost {
vc.post = post
}
}
}

Pass object to another controller connecting through segue

hello I am new to programming. So I have some basic questions and then I need the solution of the problem which I am having.
I have created a Model Class
class Trip: NSObject {
var tripTitle: String
var tripSummary: String
static var trips = [Trip]()
init(tripTitle: String, tripSummary: String) {
self.tripTitle = tripTitle
self.tripSummary = tripSummary
}
class func addTrip(tripTitle: String, tripSummary: String){
let t = Trip(tripTitle: tripTitle, tripSummary: tripSummary)
trips.append(t)
}
}
TripsDetailController
#IBAction func previewButtomPressed(sender: UIButton) {
let tripTitle = tripTitleTxt.text!
let tripSummary = tripSummaryTxt.text!
Trip.addTrip(tripTitle, tripSummary: tripSummary)
// let optionaltrip = Trip(tripTitle: tripTitle, tripSummary: tripSummary)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "ShowTripPreviewTableViewController" {
let tripPreviewTableViewController = segue.destinationViewController as! TripPreviewTableViewController
// how can I pass the object here
}
}
how can I pass the object in segue
tripPreviewTableViewController
In this class I know I have to declare a variable here also but don't know what would be the datatype and also how can I access the value
and also I want to know what would be the best approach from these two
Trip.addTrip(tripTitle, tripSummary: tripSummary)
or
let trip = Trip(tripTitle: tripTitle, tripSummary: tripSummary)
should I have to create an array and assign values or go to the second method of creating an object
Use the destinationViewController:
In the tripPreviewTableViewController you need to add new optional variable type of Trip:
var trip : Trip!
and now you can transfer your object with destinationViewController:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "ShowTripPreviewTableViewController" {
let tripPreviewTableViewController = segue.destinationViewController as! TripPreviewTableViewController
tripPreviewTableViewController.trip = (Your Trip Object)
}
}
//Update
First you need to declare your Trip object in TripsDetailController:
var tripToPass = Trip!
then orient it with one of these ways:
tripToPass = Trip(tripTitle:"title",tripSummary:"summary")
//or get the Trip out of your trips array:
tripToPass = Trip.trips[index]
after that you can pass the trip object:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "ShowTripPreviewTableViewController" {
let tripPreviewTableViewController = segue.destinationViewController as! TripPreviewTableViewController
tripPreviewTableViewController.trip = tripToPass
}
}

Ambiguous use of 'numberOfPages'

I don't understand what is ambiguous about my use of book.numberOfPages in my TableViewController. I'm not having any problems with using any of the other attributes. There shouldn't be any ambiguity here: I have defined it as a Float in the data model editor and at the top of the TableViewController.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showBookDetail" {
let indexPath:NSIndexPath = self.tableView.indexPathForSelectedRow()!
let book: AnyObject = addBookViewController.fetchedResultsController.objectAtIndexPath(indexPath) as! Book
var detailViewController:BookDetailViewController = segue.destinationViewController as! BookDetailViewController
detailViewController.title = book.name
detailViewController.pagesReadText = "\(Int(book.pagesRead))"
detailViewController.timeReadText = "\(Int(book.timeRead))"
println(book.numberOfPages)
}
}
Probably you can't declare book as AnyObject so the compiler knows that it is a Book...
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showBookDetail" {
let indexPath:NSIndexPath = self.tableView.indexPathForSelectedRow()!
let book = addBookViewController.fetchedResultsController.objectAtIndexPath(indexPath) as! Book
var detailViewController:BookDetailViewController = segue.destinationViewController as! BookDetailViewController
detailViewController.title = book.name
detailViewController.pagesReadText = "\(Int(book.pagesRead))"
detailViewController.timeReadText = "\(Int(book.timeRead))"
println(book.numberOfPages)
}
}

Resources