Issue building proper array from tableview selections - arrays

Essentially I am adding or removing the cell values to an array that is built up based on which cells are selected/deselected.
I need my array to look like this:
[{"value":"One","id":"1"},{"value":"two","id":"4"}]
Currently it looks like this:
["One", "two"]
Currently the array does not include the struct titles (id and value) and does not include the curly brackets. The values for the id and values are coming from the array populating the tableview. How can this be done?
My code so far:
var structure = [Struct]()
var selectionArray: [String] = []
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)
cell!.accessoryType = .checkmark
let item = structure[indexPath.row]
let cellvalue = item.value
selectionArray.append(cellvalue)
}
override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)
cell!.accessoryType = .none
let item = structure[indexPath.row]
let cellvalue = item.value
if let index = selectionArray.index(of: cellvalue) {
selectionArray.remove(at: index)
}
}
struct Struct: Decodable {
let id: Int
let value: String
}

You don't need to store the selectionArray array as a property at all. You can use indexPathsForSelectedRows to get all the selected rows. So you can generate the array whenever you need it.
let selectedIndexPaths = tableView.indexPathsForSelectedRows ?? []
// this contains the selected structs
let selectedStructs = selectedIndexPaths.map { structure[$0.row] }
Now you can encode it to JSON:
// remember to conform Struct to Codable!
let encoder = JSONEncoder()
do {
let jsonData = try encoder.encode(selectedStructs)
// if you want to see the encoded JSON string:
print(String(data: jsonData, encoding: .utf8)!)
} catch {
print(error)
}

Related

swift3 get the array in side closure

I would like to get the final result joblist array to use outside closure. Because I would like to setup a tableview by using Joblist array. .
let geoCoder = CLGeocoder()
geoCoder.geocodeAddressString(address) { (placemarks, error) in
if error == nil && (placemarks?.count)! > 0 {
let location2 = placemarks?[0].location
if let location1 = self.locationManager?.location {
let distanceInMeters = location1.distance(from: location2!)
let IntDis = Int(distanceInMeters)
//print(IntDis)
if IntDis < 40000 {
//print(address)
if let activityid = infoDictionary["ActivityID"] {self.newJob.ActivityID=activityid}
if let companyname = infoDictionary["CompanyName"] {self.newJob.CompanyName=companyname}
if let quantity = infoDictionary["Quantity"] {self.newJob.Quantity=quantity}
if let coupontitle = infoDictionary["Title"] {self.newJob.CouponTitle=coupontitle}
if let couponterms = infoDictionary["Terms"] {self.newJob.CouponTerms=couponterms}
if let expirdate = infoDictionary["ExpirDate"] {self.newJob.ExpirDate=expirdate}
if let contactperson = infoDictionary["ContactPerson"] {self.newJob.ContactPerson=contactperson}
if let tel = infoDictionary["TEL"] {self.newJob.TEL=tel}
self.joblist.append(self.newJob)
//print(self.joblist)
//self.tableView.reloadData()
}
}
}
}
You can do this in two ways:
Make the joblist variable global so it can be accessed from multiple places
Use a callback, which calls a new function while passing on previously gathered data. This is especially useful when the original "data getting" proces is a network task with a delay.
Global variables:
let geoCoder = CLGeocoder()
var jobList = [AnyClass]() //make a global array
geoCoder.geocodeAddressString(address) { (placemarks, error) in
...filtering code ...
joblist.append(self.newJob)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel = jobList[indexPath.row].ActivityID //or something else with the data
}
Using a callback(simple version which doesn't pass on itself to the next function):
geoCoder.geocodeAddressString(address) { (placemarks, error) in
...filtering code ...
doTableViewStuff(data: joblist)
}
func doTableViewStuff(data: [Jobs]) { //or whatever type of data
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel = data[indexPath.row].ActivityID //or something else with the data
}
}

table view dictionary array issue

i'm trying to get my tableview to index my array correctly but it keeps randomising the dictionary values shown in the table view . Where am I going wrong?
code is as follows:
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! _VCTableViewCell
// Schemes
let kbSchemes: [Int: [String]] = [
0: ["1","2","3","4","5","6"],
1: ["1","2","3","4","5","6"],
2: ["1a","1b","2a","2b","3a","3b","4"],
3: ["1a","1b","1c","1d","1e","1f"],
4: ["1a","1b","1c","2a","2b","2c"]
]
let randomSchemeIndex = Int(arc4random_uniform(UInt32(kbSchemes.count)))
let schemeArray = kbSchemes[randomSchemeIndex]
// Exercise, Sets & Reps
let randomIndex = Int(arc4random_uniform(UInt32(kbDirectory.count)))
let dictValues = Array(kbDirectory.values)
let randomArray = dictValues[randomIndex]
let randomArrayIndex = Int(arc4random_uniform(UInt32(randomArray.count)))
let randomValue = randomArray[randomArrayIndex]
let dictKeys = Array(kbDirectory.keys)
// cell control
cell.exerciseLabel?.text = dictKeys[randomIndex]
cell.setRepLabel?.text = randomValue
cell.numberLabel?.text = schemeArray?[indexPath.row]
return cell
}
I would also like to be able the .count property for the returned kbSchemeArray later on in numberOfRowsInSection but am having issues getting it into the correct scope. any suggestions and/or advice appreciated.

How to show array of objects in TableView - swift

Hello can you help me I want to display in an TableView an array of objects but only one compoment of the array.
here my code:
extension ViewController: UITableViewDataSource {
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as UITableViewCell
let index = indexPath.row as Int
for dep in autoCompleteDestino {
DestinoInstancia.idDestino = dep.idDestino!
DestinoInstancia.desDestino = dep.desDestino!
autoCompleteDestino.append(dep)
}
print(autoCompleteDestino)
cell.textLabel?.text = String(describing: autoCompleteDestino[index])
return cell
}
}
So..i want to show in this line, only the DestinoInstancia.desDestino = dep.desDestino!
cell.textLabel?.text = String(describing: autoCompleteDestino[index])
Currently shows me this way:
MTiOS.Destinos(idDestino: Optional(1), desDestino: Optional("AsunciĆ³n")), MTiOS.Destinos(idDestino: Optional(2), desDestino: Optional("Miami")), MTiOS.Destinos(idDestino: Optional(3), desDestino: Optional("Atenas")), MTiOS.Destinos(idDestino: Optional(5), desDestino: Optional("Madrid"))]
When i want to show me only:
AsunciĆ³n
Miami
Atenas
Madrid
Please Help!
I think the issue lies in the String conversion and unwrapped optionals.
Try replacing this:
cell.textLabel?.text = String(describing: autoCompleteDestino[index])
With this:
if let str = autoCompleteDestino[index].desDestino {
cell.textLabel?.text = str
}
This replacement safely unwraps the optional while also retrieving the correct string.

Table View Number of Rows not returning array value

I am adding a bunch of values to an array and I am then returning the number of values as a number of rows in a table view. This is how I add my values to the array:
func getCurrentUserSchoolOrWorkAddressAndDisplayOtherUsers() {
let currentUser = (FIRAuth.auth()?.currentUser!)
let userID = currentUser?.uid
FIRDatabase.database().reference().child("users").child(userID!).observeSingleEventOfType(.Value, withBlock: { (snapshot) in
let schoolOrWorkAddress = snapshot.value!["schoolOrWorkAddress"] as! String
FIRDatabase.database().reference().child("schoolOrWorkAddress").child(schoolOrWorkAddress).observeSingleEventOfType(.Value, withBlock: { (snapshot) in
if(!snapshot.exists()){
return
}
let locations = snapshot.value! as! NSDictionary
for (index, location) in locations.enumerate() {
FIRDatabase.database().reference().child("users").child(location.key as! String).observeEventType(.ChildAdded, withBlock: { (snapshot: FIRDataSnapshot) in
if(snapshot.exists()){
print(snapshot)
if let dictionary = snapshot.value as? [String: AnyObject] {
let user = User()
user.id = snapshot.key
user.setValuesForKeysWithDictionary(dictionary)
self.users.append(user)
print(self.users)
}
}
}, withCancelBlock: nil)
}
dispatch_async(dispatch_get_main_queue(), {
self.tableView.reloadData()
})
})
})
}
I then return the array count as the number of table view rows like this:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return users.count
}
The only problem is for some reason it does not seem to return any count other than 0. I think the problem stems from the dispatch async code above because it is the first thing that is being called in the function. It is not being called after I append all my elements to an array which should be the problem. However, when I place the dispatch async inside of the for loop instead of outside it does not even get read. I tested this using break points.
the following code is mycellforrowatindexpath code block:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(cellId, forIndexPath: indexPath) as! UserCell
let user = users[indexPath.row]
cell.textLabel?.text = user.fullName
cell.detailTextLabel?.text = user.email
if let userPhoto = user.userPhoto {
cell.profileImageView.loadImageUsingCacheWithUrlString(userPhoto)
}
return cell
}
The following is some print statement debugging I did which shows what is being appended to the array and what is the users.count value:
Basically, my question is how do I get it so that the table view is returning my actual value of my array. Once again, I think the problem stems from the dispatch async command.
Any help you have would be appreciated!

Swift2.0 - Create tableView from an array of tuples

I have an array of tuples that is created from a JSON.
typealias TagAndLocation = (tag: String, location: String)
var resultTuples = [TagAndLocation]()
for (_, subJSON) in json {
let Tag = subJSON["Tag"].string!
let Location = subJSON["Location"].string!
let tagloc = (tag: Tag, location: Location)
resultTuples.append(tagloc)
}
Then I'll use
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "CellConcert")
//PROBLEM IS HERE. I want the indexPath.row to be the position of the array of tupple
cell.textLabel?.text = resultTuples.[indexPath.row][]
return cell
}
Basically i want my tableView to have the content of concerts.
Any idea? Thanks

Resources