I am attempting to get the text of my UILabel and set it to my Parse object, but I am running into an issue setting the object to the index path of the cell. I am getting an Use of unresolved identifier 'indexPath' error at that line.
follow["following"] = self.userArray.objectAtIndex(IndexPath.row)
Here is my tableview controller:
import UIKit
class SearchUsersRegistrationTableViewController: UITableViewController {
var userArray : NSMutableArray = []
override func viewDidLoad() {
super.viewDidLoad()
var user = PFUser.currentUser()
loadParseData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return userArray.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: SearchUsersRegistrationTableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! SearchUsersRegistrationTableViewCell
let row = indexPath.row
var individualUser = userArray[row] as! PFUser
var username = individualUser.username as String
var profileImage = individualUser["profileImage"] as? PFFile
if profileImage != nil {
profileImage!.getDataInBackgroundWithBlock({
(result, error) in
cell.userImage.image = UIImage(data: result)
})
} else {
cell.userImage.image = UIImage(named: "profileImagePlaceHolder")
}
cell.usernameLabel.text = username
cell.addUserButton.tag = row
cell.addUserButton.addTarget(self, action: "addUser:", forControlEvents: .TouchUpInside)
return cell
}
func loadParseData() {
var query : PFQuery = PFUser.query()
query.findObjectsInBackgroundWithBlock {
(objects:[AnyObject]!, error:NSError!) -> Void in
if error == nil {
if let objects = objects {
println("\(objects.count) users are listed")
for object in objects {
self.userArray.addObject(object)
}
self.tableView.reloadData()
}
} else {
println("There is an error")
}
}
}
#IBAction func addUser(sender: UIButton) {
println("Button Triggered")
let addUserButton : UIButton = sender
let user : PFObject = self.userArray.objectAtIndex(addUserButton.tag) as! PFObject
var follow = PFObject(className: "Follow")
follow["following"] = self.userArray.objectAtIndex(IndexPath.row)
follow["follower"] = PFUser.currentUser().username
follow.saveInBackground()
}
}
Here is my tableview cell:
import UIKit
class SearchUsersRegistrationTableViewCell: UITableViewCell {
#IBOutlet weak var userImage: UIImageView!
#IBOutlet weak var usernameLabel: UILabel!
#IBOutlet weak var addUserButton: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
userImage.layer.borderWidth = 1
userImage.layer.masksToBounds = false
userImage.layer.borderColor = UIColor.whiteColor().CGColor
userImage.layer.cornerRadius = userImage.frame.width/2
userImage.clipsToBounds = true
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Try this
follow["following"] = self.userArray.objectAtIndex(sender.tag)
You are setting the row as tag for your button. Just use it.
you should not work with tags in that case.
to get the indexpath in your addUser function add the following:
let indexPath = tableView.indexPathForRowAtPoint(addUserButton.convertPoint(CGPointZero, toView: tableView))
then you can use that line:
follow["following"] = self.userArray.objectAtIndex(indexPath.row)
indexPath, not IndexPath
Related
I have a problem. I need that when I press a button this will automatically refresh my page putting inside it the new content. Possibly while this happens, I would like the button to do a circle animation. Thanks in advance.
class ViewControllerAvvisi: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate
{
var selfTable: NSMutableArray = NSMutableArray()
#IBOutlet weak var MessageTable: UITableView!
#IBOutlet weak var MessageTextField: UITextField!
#IBOutlet weak var SendMessage: UIButton!
var messagesArray:[String] = [String]()
override func viewDidLoad() {
super.viewDidLoad()
self.MessageTable.delegate = self
self.MessageTable.dataSource = self
self.MessageTable.delegate = self
let tapGesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "TableViewTapped")
self.MessageTable.addGestureRecognizer(tapGesture)
func retrieveMessages() {
let query = PFQuery(className: "Message")
query.findObjectsInBackgroundWithBlock {
(remoteObjects: [PFObject]?, error: NSError?) -> Void in
self.messagesArray = [String]()
for messageObject in remoteObjects! {
let messageText: String? = (messageObject as PFObject) ["Text"] as? String
if messageText != nil {
self.messagesArray.append(messageText!)
}
}
self.MessageTable.reloadData()
}
}
retrieveMessages()
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.MessageTable.dequeueReusableCellWithIdentifier("MessageCell")! as UITableViewCell
cell.textLabel?.text = self.messagesArray[indexPath.row]
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return messagesArray.count
}
#IBAction func SendMessage(sender: AnyObject) {
self.MessageTable.endEditing(true)
let NewMessage: PFObject = PFObject (className: "Message")
NewMessage["Text"] = self.MessageTextField.text
self.MessageTextField.enabled = false
self.SendMessage.enabled = false
NewMessage.saveInBackgroundWithBlock { (success:Bool, NSError) -> Void in
if (success == true) {
NSLog("Message successfully saved")
}else{
NSLog("Message didn't save")
}
self.MessageTextField.enabled = true
self.SendMessage.enabled = true
self.MessageTextField.text = ""
}
}
#IBAction func Refresh(sender: AnyObject) {
}
}
Just use the function you created to reload the new data. Move it outside of the viewDidLoad function.
Add an IBAction with the button you want to reload data and add retrieveMessages(). As you reload, new data will automatically be loaded.
#IBAction func refreshData(sender: AnyObject) {
retrieveMessages()
}
For the circle animation, I recommend using a UIActivityIndicatorView.
I am attempting to display data from Parse onto the following tableView controller. For some reason, the data is not displaying on the tableView (i.e. the rows are blank). I do not think that the data queried from Parse is being appended to the arrays. I am wondering what I'm doing wrong here.
Here's the current output:
I am using a custom prototype cell with identifier "CellTrack" class "TrackTableViewCell" and as shown below:
Here is my code in the TableViewController file:
import UIKit
import Parse
class MusicPlaylistTableViewController: UITableViewController {
var usernames = [String]()
var songs = [String]()
var dates = [String]()
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(animated: Bool) {
var query = PFQuery(className:"PlaylistData")
query.findObjectsInBackgroundWithBlock { (objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
if let objects = objects! as? [PFObject] {
self.usernames.removeAll()
self.songs.removeAll()
self.dates.removeAll()
for object in objects {
let username = object["username"] as? String
self.usernames.append(username!)
print("added username")
let track = object["song"] as? String
self.songs.append(track!)
let date = object["createdAt"] as? String
self.dates.append(date!)
self.tableView.reloadData()
}
}
} else {
print(error)
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return usernames.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CellTrack", forIndexPath: indexPath) as! TrackTableViewCell
cell.username.text = usernames[indexPath.row]
cell.songTitle.text = songs[indexPath.row]
cell.CreatedOn.text = dates[indexPath.row]
return cell
}
}
And here is my code in the "TrackTableViewCell.swift" class:
import UIKit
class TrackTableViewCell: UITableViewCell {
#IBOutlet weak var songTitle: UILabel!
#IBOutlet weak var username: UILabel!
#IBOutlet weak var CreatedOn: UILabel!
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
}
}
Execute your tableView.reloadData() in main thread.
dispatch_async(dispatch_get_main_queue(), {
self.tableViewCell.reloadData()
})
Try doing a guard let to see if those values are actually coming back as string or not. My guess would be that the value for created at never came back. Try it out and let me know.
guard let username = object["username"] as? String else {
print ("could not get username")
}
self.usernames.append(username)
print("added username")
guard let track = object["song"] as? String else {
print ("could not get song")
return
}
self.songs.append(track)
guard let date = object["createdAt"] as? String else {
print ("could not get createdAt")
return}
self.dates.append(date!)
func dequeueReusableCellWithIdentifier(_ identifier: String) -> UITableViewCell?
Return Value
A UITableViewCell object with the associated identifier or nil if no such object exists in the reusable-cell queue.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("CellTrack", forIndexPath: indexPath) as! TrackTableViewCell
if cell == nil {
// create a new cell here
cell = TrackTableViewCell(...)
}
cell.username.text = usernames[indexPath.row]
cell.songTitle.text = songs[indexPath.row]
cell.CreatedOn.text = dates[indexPath.row]
return cell
}
My app keeps crashing when I select the TableViewCell but it does not give me an error message. Hope some on can help. Below is the TableView Controller and the View Controller code. I have added the date into the cordite model and think it has something to do with that.
import UIKit
import CoreData
class DiveLogTableViewController: UITableViewController {
var myDivelog : Array<AnyObject> = []
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 viewDidAppear(animated: Bool) {
let appDel:AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let context:NSManagedObjectContext = appDel.managedObjectContext!
let freq = NSFetchRequest(entityName: "Divelog")
myDivelog = context.executeFetchRequest(freq, error: nil)!
tableView.reloadData()
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "update" {
var selectedItem: NSManagedObject = myDivelog[self.tableView.indexPathForSelectedRow()!.row] as! NSManagedObject
let ADLVC: AddDiveLogViewController = segue.destinationViewController as! AddDiveLogViewController
ADLVC.divenumber = selectedItem.valueForKey("divenumber") as! String
ADLVC.ddate = selectedItem.valueForKey("ddate") as! NSDate
ADLVC.divelocation = selectedItem.valueForKey("divelocation") as! String
ADLVC.existingItem = selectedItem
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return myDivelog.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let CellID: NSString = "Cell"
var cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier(CellID as String) as! UITableViewCell
if let ip = indexPath as NSIndexPath? {
var data: NSManagedObject = myDivelog[ip.row] as! NSManagedObject
var ddate = data.valueForKey("ddate") as! NSDate
var diveloc = data.valueForKey("divelocation") as! String
var diveno = data.valueForKey("divenumber") as! String
cell.textLabel!.text = "#\(diveno)#\(diveloc)"
cell.detailTextLabel!.text = "\(ddate),location: \(diveloc)"
}
// Configure the cell...
return cell
}
// Override to support conditional editing of the table view.
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 to support editing the table view.
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
let appDel:AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let context:NSManagedObjectContext = appDel.managedObjectContext!
if editingStyle == UITableViewCellEditingStyle.Delete {
if let tv = tableView as UITableView? {
context.deleteObject(myDivelog[indexPath.row] as! NSManagedObject)
myDivelog.removeAtIndex(indexPath.row)
tv.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Fade)
}
var error: NSError? = nil
if !context.save(&error) {
abort()
}
}
}
}
import UIKit
import CoreData
class AddDiveLogViewController: UIViewController {
#IBOutlet weak var textFieldDiveNumber: UITextField!
#IBOutlet weak var textFieldDiveLocation: UITextField!
#IBOutlet weak var textFieldDDate: UITextField!
var divenumber: String = ""
var divelocation: String = ""
var ddate = NSDate()
var datePickerView: UIDatePicker!
var existingItem: NSManagedObject!
override func viewDidLoad() {
super.viewDidLoad()
if (existingItem != nil) {
textFieldDiveNumber.text = divenumber
textFieldDiveLocation.text = divelocation
textFieldDDate.text = ddate.stringValue
}
// Do any additional setup after loading the view.
datePickerView = UIDatePicker()
datePickerView.datePickerMode = UIDatePickerMode.Date
var toolbar = UIToolbar(frame: CGRectMake(0, 0, datePickerView.frame.width, 44))
let OKButton = UIBarButtonItem(title: "OK", style: .Plain, target: self, action: "OKButtonTapped:")
toolbar.setItems([OKButton], animated: true)
self.textFieldDDate.inputView = datePickerView
self.textFieldDDate.inputAccessoryView = toolbar
}
#IBAction func saveTapped(sender: AnyObject) {
let appDel: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let contxt: NSManagedObjectContext = appDel.managedObjectContext!
let en = NSEntityDescription.entityForName("Divelog", inManagedObjectContext: contxt)
if (existingItem != nil) {
existingItem.setValue(textFieldDiveNumber.text, forKey: "divenumber")
existingItem.setValue(textFieldDiveLocation.text, forKey: "divelocation")
existingItem.setValue(textFieldDDate.text.dateValue!, forKey: "ddate")
} else {
var newItem = Divelog(entity: en!, insertIntoManagedObjectContext: contxt)
newItem.divenumber = textFieldDiveNumber.text
newItem.divelocation = textFieldDiveLocation.text
newItem.ddate = textFieldDDate.text.dateValue!
}
contxt.save(nil)
self.navigationController?.popToRootViewControllerAnimated(true)
}
#IBAction func cancelTapped(sender: AnyObject) {
self.navigationController?.popToRootViewControllerAnimated(true)
}
func OKButtonTapped(sender: UIBarButtonItem) {
self.textFieldDDate.endEditing(true)
self.textFieldDDate.text = datePickerView.date.stringValue
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I'm trying to create a button within my custom tableview cell that has the action of creating a Parse class if it isn't already created and applying the text of the label of the row that the button clicked occurred as the value for the "following" column and set the "follower" column value as the username of the current loggedin user. Currently I have an error at the let usernameLabel in the addUser IBAction that my Class does not have a member named objectAtIndex. What is the best way to achieve what I'm looking for?
I have created the outlets in SearchUsersRegistrationTableViewCell.swift
import UIKit
class SearchUsersRegistrationTableViewCell: UITableViewCell {
#IBOutlet var userImage: UIImageView!
#IBOutlet var usernameLabel: UILabel!
#IBOutlet weak var addUserButton: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
userImage.layer.borderWidth = 1
userImage.layer.masksToBounds = false
userImage.layer.borderColor = UIColor.whiteColor().CGColor
userImage.layer.cornerRadius = userImage.frame.width/2
userImage.clipsToBounds = true
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Here is my table functionality and the action that I tried to apply to my addUserButton:
import UIKit
class SearchUsersRegistrationViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var userArray : NSMutableArray = []
#IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
loadParseData()
var user = PFUser.currentUser()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func loadParseData() {
var query : PFQuery = PFUser.query()
query.findObjectsInBackgroundWithBlock {
(objects:[AnyObject]!, error:NSError!) -> Void in
if error == nil {
if let objects = objects {
println("\(objects.count) users are listed")
for object in objects {
self.userArray.addObject(object)
}
self.tableView.reloadData()
}
} else {
println("There is an error")
}
}
}
let textCellIdentifier = "Cell"
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.userArray.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(textCellIdentifier, forIndexPath: indexPath) as! SearchUsersRegistrationTableViewCell
let row = indexPath.row
var individualUser = userArray[row] as! PFUser
var username = individualUser.username as String
var profileImage = individualUser["profileImage"] as! PFFile
profileImage.getDataInBackgroundWithBlock({
(result, error) in
cell.userImage.image = UIImage(data: result)
})
cell.usernameLabel.text = username
cell.addUserButton.tag = row
cell.addUserButton.addTarget(self, action: "addUser:", forControlEvents: .TouchUpInside)
return cell
}
#IBAction func addUser(sender: UIButton){
let usernameLabel = self.objectAtIndex(sender.tag) as! String
var following = PFObject(className: "Followers")
following["following"] = usernameLabel.text
following["follower"] = PFUser.currentUser().username //Currently logged in user
following.saveInBackground()
}
#IBAction func finishAddingUsers(sender: AnyObject) {
self.performSegueWithIdentifier("finishAddingUsers", sender: self)
}
}
I'm assuming the usernameLabel is on the same contentView as the UIButton sender. If that's the case you can add a tag to the usernameLabel and do this
let usernameLabel = sender.superview.viewWithTag(/*Put tag of label here*/)
I'm on a mobile so I don't know if viewWithTag is the right name of the method, but it's something similar.
hope this helps.
You are getting the error because you are using self instead of tableView
let usernameLabel = self.objectAtIndex(sender.tag) as! String
let usernameLabel = tableView.objectAtIndex(sender.tag) as! String
However, this will still give you an error because UITableViewCell cannot be cast as a String.
This is a better option:
if let surtvc = tableView.objectAtIndex(sender.tag) as? SearchUsersRegistrationTableViewCell {
// surtvc.usernameLabel...
// the rest of your code goes here
}
I am attempting to display the users image that is saved to parse property "image". I have been able to display my username with no issue, but I can't seem to be able to get my image to appear. Should I be casting this information as UIImage? Am I correctly calling where the file is stored?
Here is my code:
import UIKit
class SearchUsersRegistrationViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var userArray : NSMutableArray = []
#IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
loadParseData()
var user = PFUser.currentUser()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func loadParseData() {
var query : PFQuery = PFUser.query()
query.findObjectsInBackgroundWithBlock {
(objects:[AnyObject]!, error:NSError!) -> Void in
if error == nil {
if let objects = objects {
println("\(objects.count) users are listed")
for object in objects {
self.userArray.addObject(object)
}
self.tableView.reloadData()
}
} else {
println("There is an error")
}
}
}
let textCellIdentifier = "Cell"
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.userArray.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(textCellIdentifier, forIndexPath: indexPath) as! SearchUsersRegistrationTableViewCell
let row = indexPath.row
var individualUser = userArray[row] as! PFUser
var username = individualUser.username as String
var profilePicture = individualUser["image"] as? UIImage
cell.userImage.image = profilePicture
cell.usernameLabel.text = username
return cell
}
#IBAction func finishAddingUsers(sender: AnyObject) {
self.performSegueWithIdentifier("finishAddingUsers", sender: self)
}
}
The photos are saved in a PFFile and not as a UIImage..
What makes your code the following:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(textCellIdentifier, forIndexPath: indexPath) as! SearchUsersRegistrationTableViewCell
let row = indexPath.row
var individualUser = userArray[row] as! PFUser
var username = individualUser.username as String
var pfimage = individualUser["image"] as! PFFile
pfimage.getDataInBackgroundWithBlock({
(result, error) in
cell.userImage.image = UIImage(data: result)
})
cell.usernameLabel.text = username
return cell
}
See more in the docs
fileprivate func getImage(withCell cell: UITableViewCell, withURL url: String) {
Alamofire.request(url).responseImage { (image) in
/* Assign parsed Image */
if let parsedImage = image.data {
DispatchQueue.main.async {
/* Assign Image */
cell.imageView?.image = UIImage(data: parsedImage)
/* Update Cell Content */
cell.setNeedsLayout()
cell.layoutIfNeeded()
}
}
}
}