self.tableview.reloaddata() not being called in swift - ios

class NewsTableViewController: UITableViewController {
#IBOutlet weak var authenticationButton: UIBarButtonItem!
var blogPosts = []
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
self.navigationItem.title = PFConfig.currentConfig().objectForKey("title") as? String
authenticationButton.enabled = true
if let authEnabled:Bool = PFConfig.currentConfig().objectForKey("adminEnabled") as? Bool {
if authEnabled {
authenticationButton.tintColor = UIView.appearance().tintColor
} else {
authenticationButton.tintColor = UIColor.darkGrayColor()
}
}
loadPosts()
//set the title
PFConfig.getConfigInBackgroundWithBlock { (var config: PFConfig!, var error: NSError!) -> Void in
if error == nil {
if let title:String = config.objectForKey("title") as? String {
self.navigationItem.title = title
}
if let authEnabled:Bool = config.objectForKey("adminEnabled") as? Bool {
if authEnabled {
self.authenticationButton.tintColor = UIView.appearance().tintColor
} else {
self.authenticationButton.tintColor = UIColor.darkGrayColor()
}
}
}
}
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 0
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return blogPosts.count
}
#IBAction func authenticate(sender: UIBarButtonItem) {
//check if enabled, and if not, get error message from config
if sender.tintColor != UIColor.darkGrayColor() {
//enabled
var authAlert = UIAlertController(title: "Authenticate", message: "Please login to access the admin page.", preferredStyle: UIAlertControllerStyle.Alert)
authAlert.addTextFieldWithConfigurationHandler({(textField: UITextField!) in
textField.placeholder = "Password"
})
authAlert.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil))
authAlert.addAction(UIAlertAction(title: "Go", style: UIAlertActionStyle.Default, handler: { (goAction) -> Void in
let textField:UITextField = authAlert.textFields![0] as UITextField
let text = textField.text
self.authenticateUser(text)
}))
self.presentViewController(authAlert, animated: true, completion: nil)
} else {
//disabled
var serverMessage = PFConfig.currentConfig().objectForKey("adminEnabledMessage") as? String
var errorMessage = UIAlertController(title: "Error", message: "The Admin Console is not enabled right now. Message from server: \(serverMessage!)", preferredStyle: UIAlertControllerStyle.Alert)
errorMessage.addAction(UIAlertAction(title: "Dismiss", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(errorMessage, animated: true, completion: nil)
}
}
//authHandlers
func authenticateUser(password: String) {
//get the server password
let serverPass = PFConfig.currentConfig().objectForKey("password") as? String
if password == serverPass {
//move them to the admin console
self.performSegueWithIdentifier("showConsole", sender: nil)
} else {
//error message
var errorMessage = UIAlertController(title: "Error", message: "Incorrect password, please try again.", preferredStyle: UIAlertControllerStyle.Alert)
errorMessage.addAction(UIAlertAction(title: "Dismiss", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(errorMessage, animated: true, completion: nil)
}
}
func loadPosts() {
let query = PFQuery(className: "Posts")
query.findObjectsInBackgroundWithBlock { (objects, error: NSError!) -> Void in
if error == nil {
self.blogPosts = objects
self.tableView.reloadData()
} else {
var errorMessage = UIAlertController(title: "Error", message: "There was an error retrieving the posts. Please try again later. \(error.localizedDescription)", preferredStyle: UIAlertControllerStyle.Alert)
errorMessage.addAction(UIAlertAction(title: "Dismiss", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(errorMessage, animated: true, completion: nil)
}
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as PostTableViewCell
// Configure the cell...
let currentPost:PFObject = blogPosts.objectAtIndex(indexPath.row) as PFObject
let title = currentPost.objectForKey("title") as String
cell.titleLabelC.text = title
let gmtFormatter:NSDateFormatter = NSDateFormatter()
gmtFormatter.dateFormat = "E MMM d # hh:mm a"
let dateString = gmtFormatter.stringFromDate(currentPost.createdAt)
cell.detailsLabelC.text = dateString
return cell
}
Here is my code for the UITableView that I added to my storyboard. For some reason, when I call self.tableView.reloadData() in loadPosts(), it won't update the table and simply won't call cellForRowAtIndexPath. Any idea why?

Your TableViewDataSource always returns 0 for the number of sections but you need at least 1. Just remove that DataSource function because it is 1 by default.

This error about multithreading.
UITableView - it is UI element. UI works only in main thread. That means that reloadData also works only in main thred.
In your code query.findObjectsInBackgroundWithBlock is async method. So reloadData will not work in this method.
You should call it in main thread through GCD.
dispatch_async(dispatch_get_main_queue(), {
self.tableView.reloadData()
})

Related

Swift 4. How can I make method return bool from Firebase completion handler

override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
if identifier == "ChosenCell" {
if let indexPath = tableView.indexPath(for: sender as! UITableViewCell) {
reference.child("List").child(storyArray[indexPath.row].name).observeSingleEvent(of: .childAdded) { snapshot in
let snapshotValue = snapshot.value as! Dictionary<String,String>
if snapshotValue["Creator"]! != self.currentUser!.email! {
//return false
//continue
} else {
let alert = UIAlertController(title: "Warning", message: "Enter password:", preferredStyle: .alert)
let action = UIAlertAction(title: "OK", style: .default) { alertAction in
let textField = alert.textFields![0] as UITextField
if textField.text! != snapshotValue["Password"]! {
//return false
}
}
alert.addTextField { textField in
textField.placeholder = "password"
}
alert.addAction(action)
self.present(alert, animated: true, completion: nil)
}
}
}
}
return true
}
When user choose cell if user is currentUser or if there is no password "ChosenCell" segue should perform.
Else alert: "Please enter password". And if the password is right "ChosenCell" segue should perform.
How can I do this?
In this case func shouldPerformSegue always returns true, because observeSingleEvent performs in background thread and shouldPerformSegue doesn't wait for completion of observeSingleEvent.
You should implement logic in this way:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let name = storyArray[indexPath.row].name
reference.child("List").child(name).observeSingleEvent(of: .childAdded) { snapshot in
let snapshotValue = snapshot.value as! [String : String]
if snapshotValue["Creator"]! == self.currentUser!.email! { // user is the creator of this cell, so perform segue
performSegue(withIdentifier: "ChosenCell", sender: nil)
} else { // user is not the creator of this cell
let alert = UIAlertController(title: "Warning", message: "Enter password:", preferredStyle: .alert)
let action = UIAlertAction(title: "OK", style: .default) { alertAction in
let textField = alert.textFields!.first
if textField.text! != snapshotValue["Password"]! { // wrong password
// show error message
} else { // right password
performSegue(withIdentifier: "ChosenCell", sender: nil)
}
}
alert.addTextField { textField in
textField.placeholder = "password"
}
alert.addAction(action)
present(alert, animated: true)
}
}
}

iOS Swift 3: does retain cycle happens in this case?

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CheckoutCell") as! CheckoutCell
let product = shoppingCart[indexPath.row]
var tfQuantity : UITextField!
cell.clickEditAction = { [weak self] celll in
guard let ss = self else { return }
let alert = UIAlertController(title: nil, message: "Enter new quantity", preferredStyle: .alert)
alert.addTextField { (textfield) in
tfQuantity = textfield
}
let okAction = UIAlertAction(title: "OK", style: .default) { (action) in
if tfQuantity.text == ""{
return
}
if let newQuantity = Int(tfQuantity.text){
product.quantity = newQuantity
self.tbvCheckout.reloadData()
}
return
}
alert.addAction(okAction)
self.present(alert, animated: true, completion: nil)
}
return cell
}
This line of code:
self.tbvCheckout.reloadData()
If I don't use [weak self] or [unowned self], does it create retain cycle between current object & UIAlertAction instance?
What if I use this code instead: tableView.reloadData()?
Couple of things:
First, You have created a weak reference, but I don't see you using it in the code.
guard let ss = self else { return }
Any reference to self should be via this weak self variable "ss" that you have created.
Second, The alert action block should also have weak reference to self
let okAction = UIAlertAction(title: "OK", style: .default) { [weak self] (action) in
if tfQuantity.text == ""{
return
}
if let newQuantity = Int(tfQuantity.text){
product.quantity = newQuantity
self?.tbvCheckout.reloadData()
}
return
}

Parsing JSON Tableview Information as Separate Strings

I am currently trying to use information in Tableview cells that I have populated with JSON to execute various operations but I am unable to call the specific information due to the fact that it isn't in individual strings. Is there any way to take the group of data I have pulled into each tableview cell and turn it into a series of individual strings? Here is what I currently have:
import UIKit
import GoogleMobileAds
class OngoingViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var userUsernameLabel: UILabel!
#IBOutlet weak var bannerView: GADBannerView!
#IBOutlet weak var ongoingTable: UITableView!
var list:[MyStruct] = [MyStruct]()
struct MyStruct
{
var user1 = ""
var user2 = ""
var wager = ""
var amount = ""
init(_ user1:String, _ user2:String, _ wager:String, _ amount:String)
{
self.user1 = user1
self.user2 = user2
self.wager = wager
self.amount = amount
}
}
override func viewDidLoad() {
super.viewDidLoad()
let username = UserDefaults.standard.string(forKey: "userUsername")!
userUsernameLabel.text = username
/// The banner view.
print("Google Mobile Ads SDK version: " + GADRequest.sdkVersion())
bannerView.adUnitID = "ca-app-pub-3940256099942544/2934735716"
bannerView.rootViewController = self
bannerView.load(GADRequest())
ongoingTable.dataSource = self
ongoingTable.delegate = self
get_data("http://cgi.soic.indiana.edu/~team10/ongoingWagers.php")
}
func get_data(_ link:String)
{
let url:URL = URL(string: link)!
var request = URLRequest(url:url);
request.httpMethod = "POST";
let postString = "a=\(userUsernameLabel.text!)";
request.httpBody = postString.data(using: String.Encoding.utf8);
let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
self.extract_data(data)
}
task.resume()
}
func extract_data(_ data:Data?)
{
let json:Any?
if(data == nil)
{
return
}
do{
json = try JSONSerialization.jsonObject(with: data!, options: [])
}
catch
{
return
}
guard let data_array = json as? NSArray else
{
return
}
for i in 0 ..< data_array.count
{
if let data_object = data_array[i] as? NSDictionary
{
if let data_user1 = data_object["id"] as? String,
let data_user2 = data_object["id2"] as? String,
let data_wager = data_object["wager"] as? String,
let data_amount = data_object["amount"] as? String
{
list.append(MyStruct(data_user1, data_user2, data_wager, data_amount))
}
}
}
refresh_now()
}
func refresh_now()
{
DispatchQueue.main.async(
execute:
{
self.ongoingTable.reloadData()
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return list.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.ongoingTable.dequeueReusableCell(withIdentifier: "owcell", for: indexPath) as! OngoingTableViewCell
cell.infoLabel.text = list[indexPath.row].user1 + " " + list[indexPath.row].user2 + " " + list[indexPath.row].wager + " " + list[indexPath.row].amount
cell.user1Button.tag = indexPath.row
cell.user1Button.addTarget(self, action: #selector(OngoingViewController.user1Action), for: .touchUpInside)
cell.user2Button.tag = indexPath.row
cell.user2Button.addTarget(self, action: #selector(OngoingViewController.user2Action), for: .touchUpInside)
return cell
}
#IBAction func user1Action(sender: UIButton) {
let user1Alert = UIAlertController(title: "Wait a second!", message: "Are you sure this user has won this wager?", preferredStyle: UIAlertControllerStyle.alert)
user1Alert.addAction(UIAlertAction(title: "Yes", style: UIAlertActionStyle.default, handler: { action in
let user1ConfirmationAlert = UIAlertController(title: "Great!", message: "Please wait for the other user to confirm the winner of this wager.", preferredStyle: UIAlertControllerStyle.alert)
user1ConfirmationAlert.addAction(UIAlertAction(title: "Got It!", style: UIAlertActionStyle.default, handler: nil))
self.present(user1ConfirmationAlert, animated: true, completion: nil)
}))
user1Alert.addAction(UIAlertAction(title: "No", style: UIAlertActionStyle.default, handler: nil))
self.present(user1Alert, animated: true, completion: nil)
}
#IBAction func user2Action(sender: UIButton) {
let user2Alert = UIAlertController(title: "Wait a second!", message: "Are you sure this user has won this wager?", preferredStyle: UIAlertControllerStyle.alert)
user2Alert.addAction(UIAlertAction(title: "Yes", style: UIAlertActionStyle.default, handler: { action in
let user2ConfirmationAlert = UIAlertController(title: "Great!", message: "Please wait for the other user to confirm the winner of this wager.", preferredStyle: UIAlertControllerStyle.alert)
user2ConfirmationAlert.addAction(UIAlertAction(title: "Got It!", style: UIAlertActionStyle.default, handler: nil))
self.present(user2ConfirmationAlert, animated: true, completion: nil)
}))
user2Alert.addAction(UIAlertAction(title: "No", style: UIAlertActionStyle.default, handler: nil))
self.present(user2Alert, animated: true, completion: nil)
}
}
Here is the OngoingTableViewCell subclass:
import UIKit
class OngoingTableViewCell: UITableViewCell {
#IBOutlet weak var infoLabel: UILabel!
#IBOutlet weak var user1Button: UIButton!
#IBOutlet weak var user2Button: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
You have an array of MyStruct structures, that contain entries for user1, user1, wager, and amount. That's good.
You're using tags on the buttons as a way of figuring out the selected cell, which is not ideal. Instead I would suggest using the sender parameter to figure out the indexPath of the cell that contains the button. See the bottom of my answer for the details of a better way to do it.
In any case, once you have a row number, you can easily get to the data for that wager by indexing into your array:
#IBAction func user1Action(sender: UIButton) {
selectedRow = sender.tag
//or, using my function:
selectedRow = tableView.indexPathForView(sender)
//Get the wager for the button the user tapped on.
let thisWager = list[selectedRow]
}
If you want to take action on the wager once the user taps a button in your UIAlertController, don't use a nil handler on the your second alert controller. Instead, pass in a closure that uses the selectedRow parameter from the code above to index into the list of wagers, or even use the thisWager local variable I show in my code.
Getting the indexPath of the button the user taps on:
I created a simple extension to UITableView that lets you pass in a UIView (like the sender from a button action) and get back the indexPath that contains that view.
That extension is dirt-simple. Here's how it looks:
public extension UITableView {
/**
This method returns the indexPath of the cell that contains the specified view
- Parameter view: The view to find.
- Returns: The indexPath of the cell containing the view, or nil if it can't be found
*/
func indexPathForView(_ view: UIView) -> IndexPath? {
let origin = view.bounds.origin
let viewOrigin = self.convert(origin, from: view)
let indexPath = self.indexPathForRow(at: viewOrigin)
return indexPath
}
}
And you can call that function from your button's actions:
#IBAction func buttonTapped(_ button: UIButton) {
if let indexPath = self.tableView.indexPathForView(button) {
print("Button tapped at indexPath \(indexPath)")
}
else {
print("Button indexPath not found")
}
}
The whole project can be found on Github at this link: TableViewExtension

Self.tableView.reloadData not working if there is no user tap or View change

I am having an issue; I have the following code that get execute in a IBAction and as you will see I have the code to execute reloadData of the tableView. The issue is if I don't touch the screen (like a tap or change of the view) no data is displayed in the tableView but as soon as I touch the screen or move the cells (like just move them up and down) then the data appears.
The following image is the code that imports the contacts, save them in core data and loads them into an Array and execute reload data.
Here is the complete code of the ViewController where this issue is happening.
import UIKit
import CoreData
import AddressBook
class ContactsViewController: UITableViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var tableviewContacts: UITableView!
//Public property that represent an array of the contacts added or copied by the user using the application
var contacts: [Contact] = []
//Public property that represent the context required to save the data in the persistance storage.
var context: NSManagedObjectContext!
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func viewWillAppear(animated: Bool) {
loadContacts()
tableviewContacts.reloadData()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return contacts.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:cellContact = tableView.dequeueReusableCellWithIdentifier("cellContact", forIndexPath: indexPath) as! cellContact
let contact = contacts[indexPath.row]
cell.labelContact.text = contact.name + " " + contact.surname
return cell
}
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return NO if you do not want the specified item to be editable.
return true
}
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
var contact = contacts[indexPath.row]
var error: NSError?
var handler: HACoreDataHandler = HACoreDataHandler()
handler.context!.deleteObject(contact)
handler.context!.save(&error)
if(error != nil){
let alert = UIAlertController(title: "Error", message: error?.description, preferredStyle: UIAlertControllerStyle.Alert)
var dismiss = UIAlertAction(title: "Dismiss", style: .Default) { (alertAction: UIAlertAction!) ->
Void in
}
alert.addAction(dismiss)
presentViewController(alert, animated: true, completion: nil)
}
contacts.removeAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
}
}
#IBAction func importContacts(sender: AnyObject) {
let status = ABAddressBookGetAuthorizationStatus()
if status == .Denied || status == .Restricted {
// user previously denied, to tell them to fix that in settings
let alert = UIAlertController(title: "Warning", message: "We need your permission to import your contacts to giftlog.", preferredStyle: UIAlertControllerStyle.Alert)
var dismiss = UIAlertAction(title: "Dismiss", style: .Default) { (alertAction: UIAlertAction!) ->
Void in
}
alert.addAction(dismiss)
self.presentViewController(alert, animated: true, completion: nil)
return
}
// open it
var error: Unmanaged<CFError>?
let addressBook: ABAddressBook? = ABAddressBookCreateWithOptions(nil, &error)?.takeRetainedValue()
if addressBook == nil {
println(error?.takeRetainedValue())
return
}
ABAddressBookRequestAccessWithCompletion(addressBook) {
granted, error in
if !granted {
// warn the user that because they just denied permission, this functionality won't work
// also let them know that they have to fix this in settings
let alert = UIAlertController(title: "Warning", message: "Please grant access to your contact first by granting the acess to Giftlog in the privacy phone setting ", preferredStyle: UIAlertControllerStyle.Alert)
var dismiss = UIAlertAction(title: "Dismiss", style: .Default) { (alertAction: UIAlertAction!) ->
Void in
}
alert.addAction(dismiss)
self.presentViewController(alert, animated: true, completion: nil)
return
}
if let people = ABAddressBookCopyArrayOfAllPeople(addressBook)?.takeRetainedValue() as? NSArray {
var handler: HACoreDataHandler = HACoreDataHandler()
var error: NSError?
for person:ABRecordRef in people{
if (ABRecordCopyValue(person, kABPersonFirstNameProperty) != nil){
var contact = NSEntityDescription.insertNewObjectForEntityForName("Contact", inManagedObjectContext: handler.context!) as! Contact
contact.name = (ABRecordCopyValue(person, kABPersonFirstNameProperty).takeRetainedValue() as? String)!
contact.surname = (ABRecordCopyValue(person, kABPersonLastNameProperty).takeRetainedValue() as? String)!
var phones : ABMultiValueRef = ABRecordCopyValue(person,kABPersonPhoneProperty).takeUnretainedValue() as ABMultiValueRef
if (ABMultiValueGetCount(phones)>0){
let phoneUnmaganed = ABMultiValueCopyValueAtIndex(phones, 0)
contact.phone = phoneUnmaganed.takeUnretainedValue() as! String
}
let emails: ABMultiValueRef = ABRecordCopyValue(person, kABPersonEmailProperty).takeRetainedValue()
if (ABMultiValueGetCount(emails)>0){
let index = 0 as CFIndex
let emailAddress = ABMultiValueCopyValueAtIndex(emails, index).takeRetainedValue() as! String
contact.email = emailAddress
}
handler.context!.save(&error)
if (error != nil){
let alert = UIAlertController(title: "Error", message: error?.description, preferredStyle: UIAlertControllerStyle.Alert)
var dismiss = UIAlertAction(title: "Dismiss", style: .Default) { (alertAction: UIAlertAction!) ->
Void in
}
alert.addAction(dismiss)
self.presentViewController(alert, animated: true, completion: nil)
} else {
self.contacts.append(contact)
self.tableviewContacts.reloadData()
} // else
} //if (ABRecordCopyValue(person, kABPersonFirstNameProperty) != nil)
} //for person:ABRecordRef in people
} // if let people
} // ABAddressBookRequestAccessWithCompletion
}
func loadContacts(){
var request = NSFetchRequest(entityName: "Contact")
let handler = HACoreDataHandler()
var error: NSError?
contacts = handler.context!.executeFetchRequest(request, error: &error) as! [Contact]
if(error != nil){
let alert = UIAlertController(title: "Error", message: error?.description, preferredStyle: UIAlertControllerStyle.Alert)
var dismiss = UIAlertAction(title: "Dismiss", style: .Default) { (alertAction: UIAlertAction!) ->
Void in
}
alert.addAction(dismiss)
presentViewController(alert, animated: true, completion: nil)
}
}
/*
// Override to support rearranging the table view.
override func tableView(tableView: UITableView, moveRowAtIndexPath fromIndexPath: NSIndexPath, toIndexPath: NSIndexPath) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return NO if you do not want the item to be re-orderable.
return true
}
*/
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
}
This image is the code that sets the label of each cell of the tableView.
Finally this is the image from the storyboard file of the view and the prototype cell
Any suggestions will be appreciated.
Thanks in advance.

Saveinbackgroundwithblock not executing

I am new to using swift/Parse and am having difficulty updating a user column in _User. The issue is that Parse is already running getObjectinBackgroundWithId, and the saveInBackground does not run (no success or error). If I run saveInBackgroundWithBlock without retrieving the user by their id, I have no problem saving.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var current = PFUser.currentUser().objectId
var userId = self.dictionary[indexPath.row]["userId"]
var query = PFQuery(className: "_User")
var user: PFObject?
self.query.getObjectInBackgroundWithId(userId) {
(success: PFObject!, error: NSError!) -> Void in
if success != nil {
success.addUniqueObject(current, forKey: "friendRequest")
user = success
}
}
var cell = tableView.cellForRowAtIndexPath(indexPath)
if cell?.accessoryType == UITableViewCellAccessoryType.Checkmark {
cell?.accessoryType = UITableViewCellAccessoryType.None
}
else {
self.searchController.active = false
let alertController = UIAlertController(title: "Alert", message: "Are you sure you want to add \(cell!.textLabel!.text!) to your friends?", preferredStyle: .Alert)
let OKAction = UIAlertAction(title: "Yes", style: .Default) { (action) in
user!.saveInBackgroundWithBlock {
(success: Bool!, error: NSError!) -> Void in
if success == true {
println("worked")
}
else {
println(error)
}
}
}
alertController.addAction(OKAction)
let cancelAction = UIAlertAction(title: "No", style: .Cancel) { (action) in
}
alertController.addAction(cancelAction)
self.presentViewController(alertController, animated: true) {
}
}
}
Any help would be greatly appreciated! Thanks

Resources