How to pass locations in a tableview cell? when select a cell navigate to the location? - swift

the problem that i want to passee 4 countries inside a tableview cells, when select a cell goes to it's country label.
what I want that when press fist cell goes to Brooklyn and the second to Queesn..etc
can someone please assist me?
..inside a tableview cell, each country in a cell and when press the cell goes to it's country? how i can do it
I want to pass these location data
this the cocde that i used so far.. the problem that when i select a cell it draw a line through all the locations.
and the delegate function
var countryArray = ["Brooklyn", "Queens", "Manhattan", "The Bronx"]
let coordinates = [ (CLLocationCoordinate2D(latitude: 40.6782, longitude: 73.9442)), (CLLocationCoordinate2D(latitude: 40.7282, longitude: 73.7949)), (CLLocationCoordinate2D(latitude: 40.7831, longitude: 73.9712)), (CLLocationCoordinate2D(latitude: 40.8448, longitude: 73.8648)) ]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return countryArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let locationCell = tableView.dequeueReusableCell(withIdentifier: LocationTableViewCell.locationCellIdentifier, for: indexPath) as! LocationTableViewCell
locationCell.countryLable.text = countryArray[indexPath.row]
// getting the location based on the country name
LocationManger.sharedLocationManager.findLocations(with: countryArray, coordinates: coordinates) { location in
self.locationArray = location
print("the current location is(location)")
}
// hide the car cell separator
locationCell.separatorInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: UIScreen.main.bounds.width)
// remove the animation when tapping the cell
locationCell.selectionStyle = .none
return locationCell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
currentLocationTableView.deselectRow(at: indexPath, animated: false)
// notify map controller to show pin at selected place
print(locationArray.count)
print(coordinates)
let location = locationArray[indexPath.row].coordinates
self.delegate?.SearchLocationController(self, didSelectLocationWith: location)
}
extension SearchLocationController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
guard !(annotation is MKUserLocation) else {
return nil
}
// set a custom pin
var annotaionView = map.dequeueReusableAnnotationView(withIdentifier: "custom")
if annotaionView == nil {
// create the view
annotaionView = MKAnnotationView(annotation: annotation, reuseIdentifier: "custom")
// taping in the point
annotaionView?.canShowCallout = true
annotaionView?.image = UIImage(named: "blueLocation")
}
else {
annotaionView?.annotation = annotation
}
return annotaionView
}
}

You are thinking about this wrong. Table view cells are views. They do not store data, they provide a view into data.
You want a model that holds an array of data, and your table view data source methods should take that data and install it into the cell for the specified IndexPath.
Use an array of structs where each element holds all the data you need: city names, their coordinates, etc.
When the user selects a cell, use the indexPath of the selected cell to look up the data for that cell in your array of structs, and pass the needed data to the view controller that will display your data (your SearchLocationController.)

Related

how to get the value of a label placed on table view cell

I have a number of cells in my tableview each containing different label values
when i tap on the cell I want that value of label in next view controller. how do I get that?
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as!
MeetingsListTableViewCell
if self.meeting.count > 0{
let eachMeeting = self.meeting[indexPath.row]
cell.meetingTimeLabel?.text = (eachMeeting["time"] as? String) ?? "No Time"
cell.meetingDateLabel?.text = (eachMeeting["date"] as? String) ?? "No Date"
cell.idLabel?.text = (eachMeeting["id"] as? String) ?? "NO ID"
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vc = UIStoryboard.init(name: "Main4", bundle:Bundle.main).instantiateViewController(withIdentifier: "MeetingDetailVC") as? MeetingDetailVC
self.navigationController?.pushViewController(vc!, animated: true)
}
i want that idLabel value to send in the next viewcontroller
Get the data always from the data source array meeting, never from the cell, for example
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let aMeeting = self.meeting[indexPath.row]
let identifier = aMeeting["id"] as! String
guard let vc = UIStoryboard.init(name: "Main4", bundle:Bundle.main).instantiateViewController(withIdentifier: "MeetingDetailVC") as? MeetingDetailVC else { return }
vc.identifier = identifier
self.navigationController?.pushViewController(vc, animated: true)
}
The code assumes that there is a property identifier in MeetingDetailVC
Notes:
For better readability you should name arrays in plural form (meetings).
The check self.meeting.count > 0 is pointless, cellForRowAt is not being called if the data source array is empty.
It's highly recommended to use a custom struct as data source rather than an array of dictionaries. You will get rid of all those annoying type casts.
Tapped cell can be accessed in didSelectRowAt function of tableVeiw. Extract tableView cell and cast int into your custom cell, after casting you can directly access value of lableId, add an optional property in MeetingDetailVC and pass value to it.

Trying to bind an output to my tableviewCell UI Element in RxSwift

I have an output that lives in my VM and based on some change I want my textfield that resides in my custom tableviewCell to change in some way. I am unsure about how to have my UItextfield that lives in the tableviewcell bind to my output.
let index = IndexPath(row: 0, section: 0)
if let cell = tbl.cellForRow(at: index) as? TableViewCell {
print(cell.textF.text)
// Do whatever you want
}
I am not sure when you want to get the data, but if you want to do this when the user touches the cell, just implement the following method of UITableViewDelegate:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) as? YourTableViewCellClass {
let cellLabelText = cell.yourTextField.text
// Do whatever you want with cellLabel
}
}

Swift: How to access the cells within a UITableView

I currently have UITableView that has one UITableViewCell within it. Within my code I created a button over this cell. When that button is pressed, the cells within it expand.
How would I go about making something expand when one of those cells are selected? Would I need to put a UITableView within the cell?
This is what I would do if I needed to bang something out in a hurry. Let each vegetable occupy its own table section, then expand or contract the section when the user toggles:
// We need some kind of data model.
class Vegetable {
init(name: String, facts: [String]) {
self.name = name
self.facts = facts
}
let name: String
let facts: [String]
var isShown: Bool = false // This flag gets toggled, which is why I've defined it as a class.
}
// And a table view controller configured for dynamic (not static!) cells. Create this in a storyboard, and change the UITableViewControllers class to VeggieTable.
class VeggieTable: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
veggieData = [Vegetable(name: "Tomato", facts: ["Number: 15", "Red Colored"]),
Vegetable(name: "Lettuce", facts: ["Good with peanut butter", "Green", "Crunchy snack"])] // etc.
}
var veggieData: [Vegetable]!
override func numberOfSections(in tableView: UITableView) -> Int {
return veggieData.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let veg = veggieData[section]
return veg.isShown ? veg.facts.count + 1 : 1
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let veg = veggieData[indexPath.section]
switch indexPath.row {
case 0:
cell.textLabel?.text = veg.name
default:
cell.textLabel?.text = veg.facts[indexPath.row - 1]
}
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let veg = veggieData[indexPath.section]
// Toggle the is shown flag:
veg.isShown = !veg.isShown
tableView.deselectRow(at: indexPath, animated: true)
// TODO: replace reloadData() with sophisticated animation.
// tableView.beginUpdates()
// tableView.insertRows() / deleteRows() etc etc.
// tableView.endUpdates()
tableView.reloadData()
}
}
Eventually you'd add table animations to make the rows appearing look smooth etc.
Hope that helps.

Swift two table view cell get the same value

I have used a tableview with 16 cells on a view controller. Each cell has a textfield and a picker view as a inputview for textfield. The odd thing is that When I choose the value for the first cell, it's fine. When I scrolled down to the last cell, the value is same as the first one. But I have never touched the last cell. Why would this happened?
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
{
// selected value in Uipickerview in Swift
answerText.text = pickerDataSource[row]
answerText.tag = row
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = myTable.dequeueReusableCellWithIdentifier("addFollowCell", forIndexPath: indexPath) as! AddFollowTableViewCell
cell.questionView.text = listQuestion1[indexPath.row]
cell.pickerDataSource = dictPicker[indexPath.row]!
cell.answerText.addTarget(self, action: #selector(AddFollowUpViewController.textFieldDidChange(_:)), forControlEvents: UIControlEvents.EditingDidEnd)
return cell
}
func textFieldDidChange(sender: UITextField){
let rowIndex: Int!
let selectValue = sender.tag
if let txtf = sender as? UITextField {
if let superview = txtf.superview {
if let cell = superview.superview as? AddFollowTableViewCell {
rowIndex = myTable.indexPathForCell(cell)?.row
dictAnswer[rowIndex] = selectValue - 1
}
}
}
}
After two days, it solved by thousands of trials:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
var cell = myTable.dequeueReusableCellWithIdentifier("addFollowCell") as! AddFollowTableViewCell
if(cell.identifier == true){
cell.answerText.text = selectedAnswerForRow[indexPath.row]
}
cell.questionView.text = listQuestion1[indexPath.row]
cell.pickerDataSource = dictPicker[indexPath.row]!
dictAnswer[indexPath.row] = cell.pickerValue
cell.answerText.addTarget(self, action: #selector(AddFollowUpViewController.textFieldDidChange(_:)), forControlEvents: UIControlEvents.EditingDidEnd)
cell.identifier = true
return cell
}
func textFieldDidChange(sender: UITextField){
let rowIndex: Int!
let cell = sender.superview?.superview as! AddFollowTableViewCell
rowIndex = myTable.indexPathForCell(cell)?.row
selectedAnswerForRow[rowIndex] = cell.answerValue
print(selectedAnswerForRow[rowIndex])
cell.answerText.text = sender.text
cell.identifier = true
}
It might have some performance issue need to be optimised , but it shows exactly what i want. LOL
You're basically recycling your views and not clearing them. That's the whole point of -dequeueReusableCellWithIdentifier:indexPath:.
Allocating and deallocating memory is very power consuming, so the system recycles every cell that goes out of viewport bounds.
You don't set the text inside answerText (I assume it's the text field that causes trouble) so its content will be kept when recycled.
Assuming you'll store user selection inside a dictionary var selectedAnswerForRow: [IndexPath:String]:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = myTable.dequeueReusableCellWithIdentifier("addFollowCell", forIndexPath: indexPath) as! AddFollowTableViewCell
cell.questionView.text = listQuestion1[indexPath.row]
cell.pickerDataSource = dictPicker[indexPath.row]!
cell.answerText.addTarget(self, action: "textFieldDidChange:"), forControlEvents: UIControlEvents.EditingDidEnd)
cell.answerText.text = self.selectedAnswerForRow[indexPath] ?? "" // add this
return cell
}
self.selectedAnswerForRow[indexPath] ?? "" returns the result or an empty string if it's not present in the dictionary.
Also, you're adding several times the action for edition control event. You have to check first if it isn't already bound.
Because the cell is reused. So you have to implement prepareForReuse() in your custom cell class and reset all the changing variables
UPDATE
See :
class MyCell : UITableViewCell {
#IBOutlet weak var myTextField : UITextField!
//Add the following
override func prepareForReuse() {
myTextField.text = nil
myTextField.inputView = myPickerView
super.prepareForReuse()
}
}

Swift - change height of mapview inside a tableView

(Look at ##Edit##)
I'm a beginner. I used google but can't find a solution for my problem.
How can I change the height of my MapView inside the tableView?
My storyboard looks like:
click here I cant post pictures
I can change the size of the MKMapView however I want but nothing changed "in real/in the emulator".
I tried to change the size of the cells with:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if(indexPath.row == 0) {
return 500
}
return 75.0
}
But indexPath.row=0 ist the first entry "Name: Test"
Can somebody explain how and why I can't change the size? How can I change the size?
Thank u for help.
EDIT
I tried it with two different cells ("Map Cell" and "listAllBakeries") and now it works with the size.
When I click on an entry there isn't an update at the "Map Cell" but on the "listAllBakeries". More than one Map
The code:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
//CODE TO BE RUN ON CELL TOUCH
//get the Location with latitude and longitude
var location = CLLocationCoordinate2D(latitude: latitude[indexPath.item], longitude: longitude[indexPath.item])
//resolution
var span = MKCoordinateSpanMake(0.003, 0.003)
var region = MKCoordinateRegion(center: location,span:span)
//here is the mistake
let cell2:ListPlacesTableViewCell = tableView.dequeueReusableCellWithIdentifier("MapCell", forIndexPath: indexPath) as! ListPlacesTableViewCell
//some Text about the Place
var annotation = MKPointAnnotation()
annotation.coordinate = location
annotation.title = namesBakeries[indexPath.item]
annotation.subtitle = "some Text"
//Zooming inside the map
cell2.Map.setRegion(region, animated: true)
cell2.Map.addAnnotation(annotation)
}
I don't really understand this. I use the right identifier (MapCell) but the section/row is wrong. How can I use the right section?
Here is my code how I fill the rows/section
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if(indexPath.section == 0) {
let cell2:ListPlacesTableViewCell = tableView.dequeueReusableCellWithIdentifier("MapCell", forIndexPath: indexPath) as! ListPlacesTableViewCell
//insert MapStuff
//addAnnotations
//MapStuff
return cell2
} else {
//Standard-Labels with text
let cell:ListPlacesTableViewCell = tableView.dequeueReusableCellWithIdentifier("listAllBakeries", forIndexPath: indexPath) as! ListPlacesTableViewCell
cell.nameLabel?.text = namesBakeries[indexPath.row]
cell.adressLabel?.text = "Test 2"
return cell
}
}
Thank for help
(I'm sorry for my english but this isn't my mothertongue).
It looks like your map is above the uiTableView rather than a separate prototype cell in your table.
Set your uiTableView up with 2 prototype cells then put the map in the first.
Then, as you have done, you can test the value of indexpath.row.
Okay I found out.
The trick is to update always the same cell.
I defined an array. Then save my Cell2 in this array and just used this Object to update my map. (My english is awful I know, maybe my code will give more information.)
class ListPlacesTableViewController: UITableViewController {
var constantCell = [ListPlacesTableViewCell?](count: 1, repeatedValue: nil)
....
//other stuff here
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if(indexPath.section == 0) {
let cell2:ListPlacesTableViewCell = tableView.dequeueReusableCellWithIdentifier("MapCell", forIndexPath: indexPath) as! ListPlacesTableViewCell
constantCell[0] = cell2
//other stuff here
}
}
//Clickable Cell Function add:
constantCell[0]!.Map.setRegion(region, animated: true)
constantCell[0]!.Map.addAnnotation(annotation)
Thanks for help