Refreshing data using Parse - ios

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.

Related

How to add search functionality to table view which has yelp api data?

I want to add restaurant category search functionality to RestaurantTableViewController which use yelp api business data. I followed basic search bar in table view tutorials but I do not do for my specific scenario. I do not differ filtered data and not filtered data in my RestaurantTableViewController when the search is active.
RestaurantTableViewController is below:
import UIKit
import CoreLocation
protocol ListActions: class {
func didTapCell(_ viewController: UIViewController, viewModel: RestaurantListViewModel)
}
class RestaurantTableViewController: UIViewController, UITableViewDelegate, FiltersViewControllerDelegate {
#IBOutlet weak var yourLocationLabel: UILabel!
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var searchBar: UISearchBar!
private let locationManager = CLLocationManager()
private let locationService = LocationService()
var filteredData: [RestaurantListViewModel]!
let appDelegate = UIApplication.shared.delegate as? AppDelegate
var viewModels = [RestaurantListViewModel]() {
didSet {
DispatchQueue.main.async {
// this no more loading, i notice it load late that is why when reload data in table view not working
}
}
}
weak var delegate: ListActions?
override func viewDidLoad() {
super.viewDidLoad()
filteredData = appDelegate!.data
userCurrentLocation()
DispatchQueue.main.async {
self.tabBarController?.tabBar.isHidden = false
}
if appDelegate?.data?.count == 0 {
tableView.setEmptyView(title: "There are no restaurants in your current location.", message: "Please change your location and try again!")
}
tableView.reloadData()
}
override func viewWillAppear(_ animated: Bool) {
if appDelegate?.data?.count == 0 {
tableView.setEmptyView(title: "There are no restaurants in your current location.", message: "Please change your location and try again!")
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
print("did appear")
self.removeActivityIndicator()
tableView.reloadData()
tableView.dataSource = self
tableView.delegate = self
DispatchQueue.main.async {
self.tabBarController?.tabBar.isHidden = false
}
}
}
extension RestaurantTableViewController: UITableViewDataSource {
// MARK: - Table view data source
func collectionSkeletonView(_ skeletonView: UITableView, cellIdentifierForRowAt indexPath: IndexPath) -> ReusableCellIdentifier {
return "RestaurantCell"
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("number of rows \(String(describing: viewModels.count))")
print(viewModels)
if appDelegate?.data?.count == 0 {
self.tableView.setEmptyView(title: "There are no restaurants in your current location.", message: "Please change your location and try again!")
}
if (self.searchBar.isUserInteractionEnabled) {
return self.filteredData.count
}
else {
return appDelegate!.data?.count ?? 0
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "RestaurantCell", for: indexPath) as! RestaurantTableViewCell
if (self.searchBar.isUserInteractionEnabled) {
let vm = filteredData?[indexPath.row]
cell.configure(with: vm!)
return cell
} else {
let vm = appDelegate!.data?[indexPath.row]
cell.configure(with: vm!)
return cell
}
}
// MARK: - Delegate
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard let detailsViewController = storyboard?.instantiateViewController(withIdentifier: "DetailsViewController")
else {return}
navigationController?.pushViewController(detailsViewController, animated: true)
let vm = appDelegate!.data?[indexPath.row]
appDelegate!.didTapCell(detailsViewController, viewModel: vm!)
if let selectedRowIndexPath = self.tableView.indexPathForSelectedRow {
self.tableView.deselectRow(at: selectedRowIndexPath, animated: true)
}
}
}
extension RestaurantTableViewController: UISearchBarDelegate {
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
filteredData = searchText.isEmpty ? appDelegate?.data : appDelegate?.data?.filter { (item: RestaurantListViewModel) -> Bool in
return item.categories[0].title.range(of: searchText, options: .caseInsensitive, range: nil, locale: nil) != nil
}
tableView.reloadData()
}
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
self.searchBar.showsCancelButton = true
}
}
My RestaurantTableViewCell data is below and I am getting restaurant table view cell data in configure function. But in RestaurantTableViewController's cellForRow method I do not differ my filtered and normal data when search is active.
class RestaurantTableViewCell: UITableViewCell {
#IBOutlet weak var cardContainerView: ShadowView!
#IBOutlet weak var restaurantImageView: UIImageView!
#IBOutlet weak var makerImageView: UIImageView!
#IBOutlet weak var restaurantNameLabel: UILabel!
#IBOutlet weak var locationLabel: UILabel!
#IBOutlet weak var restaurantType: UILabel!
let cornerRadius : CGFloat = 10.0
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
cardContainerView.layer.cornerRadius = cornerRadius
func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
cardContainerView.layer.shadowColor = UIColor.gray.cgColor
cardContainerView.layer.shadowOffset = CGSize(width: 5.0, height: 5.0)
cardContainerView.layer.shadowRadius = 15.0
cardContainerView.layer.shadowOpacity = 0.9
restaurantImageView.layer.cornerRadius = cornerRadius
restaurantImageView.clipsToBounds = true
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
func configure(with viewModel: RestaurantListViewModel) {
// For background thread
DispatchQueue.global(qos: .background).async {
DispatchQueue.main.async {
self.restaurantImageView.af_setImage(withURL: viewModel.imageUrl)
self.restaurantNameLabel.text = viewModel.name
self.locationLabel.text = "\(viewModel.formattedDistance) m"
}
}
if let restaurantType: String = String(viewModel.categories[0].title) {
self.restaurantType.text = restaurantType
}
}
}
RestaurantListViewModel is below also:
struct Business: Codable {
let id: String
let name: String
let imageUrl: URL
let distance: Double
let categories: [Category]
}
struct RestaurantListViewModel {
let name: String
let imageUrl: URL
let distance: Double
let id: String
let categories: [Category]
}
extension RestaurantListViewModel {
init(business: Business) {
self.name = business.name
self.id = business.id
self.imageUrl = business.imageUrl
self.distance = business.distance
self.categories = business.categories
}
}

Swift - tableviewcell returns empty using custom cell

I am new to swift programming and would need some help to check what is wrong in my tableviewcell. I have tried alot of great suggestions on stackoverflow.( make sure your outlets are connected, set delegate and datasource of your tableview to self)
This is my ViewController:
import UIKit
class CharacterViewController: UIViewController, UITableViewDataSource, UITableViewDelegate , APIControllerProtocol {
#IBOutlet weak var CharacterInfoView: UITableView!
var apiController:APIController!
var dataArray: [[String:Any]]?
var processcharacter= [CharacterListModel]()
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor=UIColor.white
self.CharacterInfoView.estimatedRowHeight = 44
self.CharacterInfoView.rowHeight = UITableViewAutomaticDimension
self.CharacterInfoView.dataSource = self
self.CharacterInfoView.delegate = self
apiController = APIController()
apiController.delegate=self
self.navigationItem.title = "Character"
self.view.showLoading()
apiController.getCharacterData{ (statusCode, data, response, error) -> () in
self.view.stopLoading()
if(statusCode == nil)
{
self.view.showServiceNotAvailableMessage(self)
}
if !(error == nil)
{
self.view.showServiceNotAvailableMessage(self)
}
if statusCode == 200
{
do
{
self.processcharacter= CharacterListData.processData(data: data)
self.CharacterInfoView.reloadData()
}
catch(_ as NSError)
{
}
}
else
{
return
}
}
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if self.dataArray == nil
{
return 0
}
else
{
return processcharacter.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier:"Cell", for:indexPath) as! CharacterTableViewCell
var processcharacters= processcharacter[indexPath.row]
cell.location.text = processcharacters.location
cell.name.text = processcharacters.name
cell.characterID.text = processcharacters.characterID
cell.time.text = processcharacters.lastlocatedtime
if wecares.sos == true {
processcharacters.imagebutton = UIImage(named: "sos_icon")!
}
else{
processcharacters.imagebutton = UIImage(named: "null_button")!
}
cell.button.image = processcharacters.imagebutton
return cell
}
func reachabilityChanged(_ status: Bool) {
}
}
This is my subclass for my ViewController:
import Foundation
class CharacterListDataHelper: NSObject {
static func processData(data: AnyObject?) -> [CharacterListModel]
{
var modelList:[CharacterListModel] = [CharacterListModel]()
let darr = try? JSONSerialization.jsonObject(with: data! as! Data, options: .mutableLeaves) as! [[String:Any]]
var dataModel:CharacterListModel
for obj in darr!
{
dataModel = CharacterListModel()
dataModel.location = obj["playerLocation"] as! String
dataModel.name = obj["playerName"] as! String
dataModel.characterID= obj["playerID"] as! String
dataModel.lastlocatedtime = obj["lastUpdatedTime"] as! String
}
modelList.append(dataModel)
}
return modelList
}
}
This is my Model:
import Foundation
struct CharacterListModel {
var name: String?
var characterID: String?
var location: String?
var lastlocatedtime: String?
var imagebutton: UIImage?
var sos: Bool?
}
This is my TableViewCell:
class CharacterTableViewCell: UITableViewCell {
#IBOutlet weak var name: UILabel!
#IBOutlet weak var characterID: UILabel!
#IBOutlet weak var location: UILabel!
#IBOutlet weak var lastlocatedtime: UILabel!
#IBOutlet weak var button: UIImageView!
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
}
Thanks in advance!
Don't fetch data in viewDidLoad() method. Fetch in viewWillAppear and reload after getting data.

how to insert data from string to Sqlite in Swift3?

I have a problem that I have tried to insert string data to Sqlite. I want to do is in my Details ViewController if user press Like button, the word and meaning of string pass into Sqlite file that show in Favourite ViewController. Below is my DetailsVC code.
import UIKit
import AVFoundation
class DetailsVC: UIViewController, UITextViewDelegate {
#IBOutlet weak var wordLbl: UILabel!
#IBOutlet weak var meaningLbl: UITextView!
#IBOutlet weak var sysWordLbl: UILabel!
#IBOutlet weak var sysWordsLbl: UILabel!
#IBOutlet weak var anyWordsLbl: UILabel!
#IBOutlet weak var anyWordLbl: UILabel!
#IBOutlet weak var wordImg: UIImageView!
#IBOutlet weak var buSound: UIButton!
#IBOutlet weak var buLike: UIButton!
#IBOutlet weak var menuBtn: UIButton!
//Data from HomeVC
var data:Data?
var fdatas = [FData]()
var favouriteVC = FavouriteVC()
override func viewDidLoad() {
super.viewDidLoad()
meaningLbl.delegate = self
wordLbl.text = "\((data?._word.capitalized)!) \((data?._phonetic)!)"
self.meaningLbl.text = data?._meaning
self.sysWordsLbl.text = data?._meaning
self.anyWordsLbl.text = data?._meaning
self.sysWordLbl.text = "Synonym"
self.anyWordLbl.text = "Antonym"
meaningLbl.font = UIFont(name: FONT_REGULAR, size: 24.0)
}
#IBAction func buMenu(_ sender: Any) {
//menu
dismiss(animated: true, completion: nil)
}
#IBAction func buSound(_ sender: Any) {
//Todo: speak the word
if buSound.isEnabled == true{
buSound.setImage(UIImage(named: "volume-2.png"), for: .normal)
}else{
buSound.setImage(UIImage(named: "volume-un-2.png"), for: .normal)
}
let utTerance = AVSpeechUtterance(string: "\((data?._word)!)")
let synthesize = AVSpeechSynthesizer()
utTerance.voice = AVSpeechSynthesisVoice(language: "en-gb")
synthesize.speak(utTerance)
}
#IBAction func buLike(_ sender: Any) {
//Todo: Click Like
if buLike.isEnabled == true{
buLike.setImage(UIImage(named: "heart.png"), for: .normal)
//Save data to Database
let word = data?._word ?? ""
let meaning = data?._meaning ?? ""
do{
let favData = FData(word: word, meaning: meaning)
self.fdatas.append(favData)
print("\(word), \(meaning)")
}catch{
print(error)
}
}else{
buSound.setImage(UIImage(named: "heart-un.png"), for: .normal)
}
//FavouriteVC.insertRowsAtIndexPaths([NSIndexPath(forRow: fdatas.count-1, inSection: 0)], withRowAnimation: .Fade)
}
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
self.view.endEditing(true);
return false;
}
}
My FavouriteVC
import UIKit
import SwipeCellKit
import SQLite
class FavouriteVC: UIViewController,UITableViewDelegate,UITableViewDataSource, SwipeTableViewCellDelegate{
//TabelView
#IBOutlet weak var fTableView: UITableView!
//Variables
var fdata = [FData]()
override func viewDidLoad() {
super.viewDidLoad()
// FtableView
fTableView.delegate = self
fTableView.dataSource = self
//reload Data
fTableView.reloadData()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return fdata.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: FAVOURITE_CELL, for: indexPath) as? FavouriteCell{
cell.configureCell(fdata: fdata[indexPath.row])
//cell.delegate = self
return cell
}
return FavouriteCell()
}
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> [SwipeAction]? {
guard orientation == .right else { return nil }
let deleteAction = SwipeAction(style: .destructive, title: "Delete") { action, indexPath in
// handle action by updating model with deletion
}
// customize the action appearance
deleteAction.image = UIImage(named: "delete")
return [deleteAction]
}
}
FData.swif
import Foundation
class FData {
//let id: Int64?
var word: String
var meaning: String
//var address: String
init(id: Int64) {
// self.id = id
word = ""
meaning = ""
//address = ""
}
init(word: String, meaning: String) {
// self.id = id
self.word = word
self.meaning = meaning
//self.address = address
}
}
FavouriteData Instance
import UIKit
import SQLite
class FavouriteData{
static let instance = FavouriteData()
private let db: Connection?
private let words = Table("words")
private let id = Expression<Int64>("id")
private let wordL = Expression<String?>("word")
private let meaningL = Expression<String?>("shanword_uni")
//private let address = Expression<String>("address")
private init() {
let path = NSSearchPathForDirectoriesInDomains(
.documentDirectory, .userDomainMask, true
).first!
do {
db = try Connection("\(path)/favourite.sqlite")
} catch {
db = nil
print ("Unable to open database")
}
createTable()
}
func createTable() {
do {
try db!.run(words.create(ifNotExists: true) { table in
table.column(id, primaryKey: true)
table.column(wordL)
//table.column(phone, unique: true)
table.column(meaningL)
})
} catch {
print("Unable to create table")
}
}
func addData(word: String, meaning: String) -> Int64? {
do {
let insert = words.insert(wordL <- word, meaningL <- meaning)
let id = try db!.run(insert)
print("Save: \(id)")
return id
} catch {
print("Insert failed")
return -1
}
}
func getData() -> [FData] {
var contacts = [FData]()
do {
for contact in try db!.prepare(self.words) {
contacts.append(FData(
// id: contact[id],
word: contact[wordL]!,
meaning: contact[meaningL]!))
}
} catch {
print("Select failed")
}
return contacts
}
func deleteData(index: Int64) -> Bool {
do {
let contact = words.filter(id == index)
try db!.run(contact.delete())
return true
} catch {
print("Delete failed")
}
return false
}
}
But, there is not cell of row in the FavouriteVC. How to fix this? Please help me.
Best,
Sai Tawng Pha
I have solved my problem by add one line of code. In my FavouriteVC class, just add it under ViewdidLoad function " fdata = FavouriteData.instance.getData() ".
Here is my complete code.
import UIKit
import SwipeCellKit
import SQLite
class FavouriteVC: UIViewController,UITableViewDelegate,UITableViewDataSource, SwipeTableViewCellDelegate{
//TabelView
#IBOutlet weak var fTableView: UITableView!
//Variables
var fdata = [FData]()
override func viewDidLoad() {
super.viewDidLoad()
// FtableView
fTableView.delegate = self
fTableView.dataSource = self
//reload Data
fTableView.reloadData()
//Get Data
fdata = FavouriteData.instance.getData()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return fdata.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: FAVOURITE_CELL, for: indexPath) as? FavouriteCell{
cell.configureCell(fdata: fdata[indexPath.row])
//cell.delegate = self
return cell
}
return FavouriteCell()
}
func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> [SwipeAction]? {
guard orientation == .right else { return nil }
let deleteAction = SwipeAction(style: .destructive, title: "Delete") { action, indexPath in
// handle action by updating model with deletion
}
// customize the action appearance
deleteAction.image = UIImage(named: "delete")
return [deleteAction]
}
}

Swift Use of Unresolved Identifier 'IndexPath' TableView Cell Button

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

Swift Adding Button Action to TableView Cell

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
}

Resources