Perform segues when I want - ios

Evening, I have 2 show segues in my VC. But I want to fires these segues only when my pickerView has a row.count > 0.
This is what I have:
Override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "searchImages" {
if pickerView.numberOfRows(inComponent: 0) > 0 {
let controller = (segue.destination) as! WebViewController
//replacing " " with "+" for google search queries
let type: WebViewController.SearchType = .image
let queryString = String(nameLabel.text!.characters.map {
$0 == " " ? "+" : $0
})
controller.searchType = type
controller.queryString = queryString
print("2")
}
}
if segue.identifier == "searchWiki" {
if pickerView.numberOfRows(inComponent: 0) > 0 {
let controller = (segue.destination) as! WebViewController
//replacing " " with "+" for google search queries
let type: WebViewController.SearchType = .wiki
let queryString = String(nameLabel.text!.characters.map {
$0 == " " ? "+" : $0
})
controller.searchType = type
controller.queryString = queryString
}
}
}
I know I should use: ShouldperformSomething. But I don't know hot use it.
Any tips?

You should implement shouldPerformSegue instead of checking pickerView.numberOfRows(inComponent: 0) > 0 in your prepareForSegue method.
P.S: Swift 3 Code (I assume that this is what you want).
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
return pickerView.numberOfRows(inComponent: 0) > 0
}
Now, prepareForSegue method should be similar to:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "searchImages" {
let controller = (segue.destination) as! WebViewController
//replacing " " with "+" for google search queries
let type: WebViewController.SearchType = .image
let queryString = String(nameLabel.text!.characters.map {
$0 == " " ? "+" : $0
})
controller.searchType = type
controller.queryString = queryString
print("2")
}
if segue.identifier == "searchWiki" {
let controller = (segue.destination) as! WebViewController
//replacing " " with "+" for google search queries
let type: WebViewController.SearchType = .wiki
let queryString = String(nameLabel.text!.characters.map {
$0 == " " ? "+" : $0
})
controller.searchType = type
}
}
Hope this helped.

You shouldn't be doing the check on the prepare delegate of the UIStoryboardSegue, but on the shouldPerform:
override func shouldPerformSegueWithIdentifier(identifier: String!, sender: AnyObject!) -> Bool {
return pickerView.numberOfRows(inComponent: 0) > 0
}

Related

Could not cast value of type 'TableViewController' to 'NSString'

I'm getting following error in the fourth line of below code...
Thread 1: signal SIGABRT, and the output says Could not cast value of type 'JobTableViewController' (0x10a20cb80) to 'NSString' (0x10cc5a2a8).
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "toDetails" {
let detailController = segue.destination as! JobDetailViewController
detailController.valueToPass = sender as! String
}
}
Job.swift:
class Job {
var text: String = ""
let ref: DatabaseReference!
init(text: String) {
self.text = text
ref = Database.database().reference().child("jobs").childByAutoId()
}
init(snapshot: DataSnapshot)
{
ref = snapshot.ref
if let value = snapshot.value as? [String : Any] {
text = value["text"] as! String
}
}
func save() {
ref.setValue(toDictionary())
}
func toDictionary() -> [String : Any]
{
return [
"text" : text,
]
}
}
Your problem is that in performSegue you send self ( which is of type JobTableViewController) as sender parameter like this
self.performSegue(withIdentifier: "toDetails", sender: self)
and here cast it to
sender as! String
so convert it to
self.performSegue(withIdentifier: "toDetails", sender:"sendedStr")

swift ios how to access data from a collection view

I have code below in a collection view and its result, what I want to know is how to access those data from my collection view to my function prepare. I want to get the value of getTempDetails like
getTempDetails["name"] as! String
to be the value of my
destination.chore_name = getTempDetails["name"] as! String
but I can't seem to access it. thanks
code for prepare
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let distanation = segue.destination as? ChoreDetailsViewController {
distanation.chore_name = "Hi"
}
}
code for
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// handle tap events
// print("You selected cell #\(indexPath.item)!")
// print("emong gepili:" , titleArray[indexPath.row])
if indexPath.row == 0 {
performSegue(withIdentifier: "goToSegue", sender: nil)
} else {
performSegue(withIdentifier: "gotoDetails", sender: nil)
print("You selected cell #\(indexPath.item)!")
if let getTempDetails: [String : Any] = getAllDetail[indexPath.row] {
print("You selected ID #\( getTempDetails["reward"] as? String ?? "" )!")
print("You selected ID #\( getTempDetails["desc"] as? String ?? "" )!")
print("You selected ID #\( getTempDetails["sched"] as? String ?? "" )!")
Possibly you can use:
var strReward:String = String()
var strDesc:String = String()
var sreSched:String = String()
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if indexPath.row == 0 {
performSegue(withIdentifier: "goToSegue", sender: nil)
} else {
performSegue(withIdentifier: "gotoDetails", sender: nil)
print("You selected cell #\(indexPath.item)!")
if let getTempDetails: [String : Any] = getAllDetail[indexPath.row] {
strReward = (getTempDetails["reward"] as? String)!
strDesc = (getTempDetails["desc"] as? String)!
sreSched = (getTempDetails["sched"] as? String)!
}
}
}
Pass this Data to next VC or can use them in any way you want
Note:- I am not sure what data type is the data coming, I have assumed it to be a String type. You can use accordingly
use the keyword of indexPathsForSelectedItems for colletionview
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
if segue.identifier == "gotoDetails" ,
let nextScene = segue.destination as? ChoreDetailsViewController ,
let indexPath = self.yourCollectionViewName. indexPathsForSelectedItems().first {
if let getTempDetails: [String : Any] = getAllDetail[indexPath.item] {
print("You selected ID #\( getTempDetails["reward"] as? String ?? "" )!")
print("You selected ID #\( getTempDetails["desc"] as? String ?? "" )!")
print("You selected ID #\( getTempDetails["sched"] as? String ?? "" )!")
nextScene.chore_name = getTempDetails["name"] as! String
}
}
}
You can store last selected items data in class var
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if indexPath.row == 0 {
performSegue(withIdentifier: "goToSegue", sender: nil)
} else {
if let getTempDetails: [String : Any] = getAllDetail[indexPath.row],
let name = getTempDetails["name"] as? String {
selectedChoreName = name
performSegue(withIdentifier: "gotoDetails", sender: nil)
}
and then
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let distanation = segue.destination as? ChoreDetailsViewController {
distanation.chore_name = selectedChoreName
selectedChoreName = "" //optional
}
}

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

passing data with performSegueWithIdentifier nil

I have the segue setup as:
and the tableView row selection:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
// Ensure controller knows which dataset to pull from,
// so detail view is correct
var friendChat: Friend!
if searchController.active && searchController.searchBar.text != "" {
friendChat = filterMappedFriends[indexPath.row]
} else {
friendChat = mappedFriends[indexPath.row]
}
// Now set the conditional cases: if a friend then chat, if user then friend request if not user then can invite them:
if(friendChat.statusSort == 2) {
self.performSegueWithIdentifier("showIndividualChat", sender: friendChat)
} else if (friendChat.statusSort == 1) {
print("Can invite to be friend")
} else if (friendChat.statusSort == 0) {
print("Invite to Feast")
}
}
and the prepareForSegue:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let indexPath = tableView.indexPathForSelectedRow {
// Ensure controller knows which dataset to pull from,
// so detail view is correct
let friendChat: Friend
if searchController.active && searchController.searchBar.text != "" {
friendChat = filterMappedFriends[indexPath.row]
} else {
friendChat = mappedFriends[indexPath.row]
}
// Now set the conditional cases: if a friend then chat, if user then friend request if not user then can invite them:
if segue.identifier == "showIndividualChat" {
let controller = segue.destinationViewController as! IndividualChatController
controller.friendChat = friendChat
controller.senderId = Global.sharedInstance.userID
controller.senderDisplayName = Global.sharedInstance.userName
}
}
}
However, the object friendChat, seen in controller.friendChat, of the destination controller is always nil.
How can I pass the data:
controller.friendChat = friendChat
controller.senderId = Global.sharedInstance.userID
controller.senderDisplayName = Global.sharedInstance.userName
to the destination controller successfully?
The first thing you are doing in didSelectRowAtIndexPath is deselecting the row, so when you try and access the selected row in prepareForSegue you are going to get no row selected.
Since you are passing the Friend instance as your sender to performSegueWithIdentifier you can just say let friendChat = sender as? Friend in prepareForSegue;
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
if segue.identifier == "showIndividualChat" {
if let friendChat = sender as? Friend {
let controller = segue.destinationViewController as! IndividualChatController
controller.friendChat = friendChat
controller.senderId = Global.sharedInstance.userID
controller.senderDisplayName = Global.sharedInstance.userName
}
}
}
For Swift 3
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
if segue.identifier == "showIndividualChat" {
if let friendChat = sender as? Friend {
let controller = segue.destination as! IndividualChatController
controller.friendChat = friendChat
controller.senderId = Global.sharedInstance.userID
controller.senderDisplayName = Global.sharedInstance.userName
}
}
}

Passing the Object from one ViewController to another

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

Resources