Reload particular section on button click in swift 4 - ios

I am trying to reload a particular section on button click in swift 4.For that,I am using following code:
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView:CustomCell = tableView.dequeueReusableCell(withIdentifier: "reuseCell") as! CustomCell
let dict:[String:Any]=array[section]
let firstKey = Array(dict.keys)[0]
headerView.categoryLabel.text=firstKey
headerView.categoryLabel.textColor = UIColor.black
currentSection=section
print("value of section and current section here %#%#",section,currentSection)
let tapRecognizer = UIButton()
tapRecognizer.frame = CGRect.init(x: 0, y:10, width:self.tableView.frame.size.width, height:50)
//tapRecognizer.backgroundColor=UIColor.red
tapRecognizer.tag=section
tapRecognizer.addTarget(self, action: #selector(tapOnHeaderView(_sender:)), for: .touchUpInside)
headerView.addSubview(tapRecognizer)
return headerView;
}
#objc func tapOnHeaderView(_sender:UIButton){
print("value of sender tag","\(_sender.tag)")
onReload = true
print("value of index vala tag",IndexSet(integer: _sender.tag))
let sectionToReload = 0
let indexSet: IndexSet = [sectionToReload]
self.tableView.reloadSections(indexSet, with: .automatic)
}
extension ViewController:UITableViewDelegate{
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if(indexPath.section==0){
if(!onReload){
return 0
}else{
return 40
}}
else{
if(!onReload){
return 0
}else{
return 40
}
}
}
When I click on any button ,it is expected that only section 0 gets reload. But, infact when I click on button section 0 and section 1 both gets reloaded.Kindly help me to resolve this problem.

#objc func tapOnHeaderView(_sender:UIButton){
print("value of sender tag","\(_sender.tag)")
onReload = true
print("value of index vala tag",IndexSet(integer: _sender.tag))
self.tableView.reloadSections([0], with: .automatic)
}
Please replace with this code and check whether it works for you

Related

Cell touch action is not responding on short touches in TableView

I have a Scene in storyboard that contains HistoryTable with historyCell and own UserHistoryViewCell view. This cell and also table is set to User interaction Enabled in Traits and Interaction sections. Scrolling is disabled and Delay Touch Down is also disabled. This cell is not responding at didSelectRowAt func at short click (only when pressing longer than 5? secs). I have a Tap Gesture Recognizer in my Scene and also another table with same problem. I tried to disable Tap Gesture Recognizer, but it seems that it doesn't do anything special. I'm not sure where is problem, I have my tables delegated and using the code bellow. I also provide screenshots of Attributes inspector for the table and cell. Btw. My second table has sections, so its little bit messy.
Second Btw. I have delay touch down enabled at the screenshot, because it has no effect at all. Third Btw. I have historyButton in my historyTable which is for removing old records. It has no impact at the cell itself (I think) because same stuff happens to my second table without this button. Also it worked before I added sections to my second table.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var counter = 0
if tableView.tag == 1 {
counter = (UserDefaults.standard.stringArray(forKey: "HistoryArray") ?? [String]()).count
let base = 60
self.historyTableHeightConstraint.constant = CGFloat(base) + CGFloat(counter) * 40
} else {
switch section {
case 0:
counter = presenter.storelist?.count ?? 0
case 1:
counter = presenter.storelist?.count ?? 0
default:
counter = 0
notFoundLabel.isHidden = false
}
}
return counter
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableView.tag == 1 {
let defaults = UserDefaults.standard
let userSearchHistory = defaults.stringArray(forKey: "HistoryArray") ?? [String]()
let cell = tableView.dequeueReusableCell(withIdentifier: "historyCell", for: indexPath) as! UserHistoryTableViewCell
cell.titleLabel.text = userSearchHistory.reversed()[indexPath.row]
cell.historyButton.addTarget(self, action: #selector(buttonTapped(_:)), for: .touchUpInside)
cell.historyButton.tag = indexPath.row
if self.editable == true {
let newImage = UIImage(named: "RemoveIcon")
cell.historyButton.setImage(newImage, for: .normal)
cell.historyButton.isEnabled = true
} else {
let newImage = UIImage(named: "searchHistoryIcon")
cell.historyButton.setImage(newImage, for: .normal)
cell.historyButton.isEnabled = false
}
return cell
} else {
switch indexPath.section {
case 0:
let cell = tableView.dequeueReusableCell(withIdentifier: "shopSearchCell", for: indexPath) as! ShopSearchTableViewCell
cell.shopLabel.text = presenter.storelist?[indexPath.row].storename
return cell
case 1:
let cell = tableView.dequeueReusableCell(withIdentifier: "SearchResultCell", for: indexPath) as! SearchResultCell
cell.SearchResultLabel.text = presenter.storelist?[indexPath.row].storename
return cell
default:
return UITableViewCell()
}
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print(#function + "\(indexPath.row)")
}
func tableView(_ tableView: UITableView, titleForHeaderInSection
section: Int) -> String? {
if tableView.tag == 2 {
if section == 0 {
if self.tableView(tableView, numberOfRowsInSection: section) > 0 {
return "Search shop"
} else {
return nil
}
} else {
if self.tableView(tableView, numberOfRowsInSection: section) > 0 {
return "Search"
} else {
return nil
}
}
} else {
return nil
}
}
// Sectionæ•°
func numberOfSections(in tableView: UITableView) -> Int {
if tableView.tag == 2 {
return 2
}
return 1
}

Swift TableView insert row below button clicked

I am new to Swift and I am using Swift 4.2 . I have a TableView with a label and button . When I press a button I would like to add a new row directly below the row in which the button was clicked . Right now when I click a button the new row gets added to the bottom of the TableView every time. I have been looking at posts on here but haven't been able to get it working this is my code base . I have a method called RowClick I get the indexpath of the row that was clicked but do not know how to use that to get the new row to appear directly below the clicked row .
class ExpandController: UIViewController,UITableViewDelegate,UITableViewDataSource {
#IBOutlet weak var TableSource: UITableView!
var videos: [String] = ["FaceBook","Twitter","Instagram"]
override func viewDidLoad() {
super.viewDidLoad()
TableSource.delegate = self
TableSource.dataSource = self
TableSource.tableFooterView = UIView(frame: CGRect.zero)
// Do any additional setup after loading the view.
}
#IBAction func RowClick(_ sender: UIButton) {
guard let cell = sender.superview?.superview as? ExpandTVC else {
return
}
let indexPath = TableSource.indexPath(for: cell)
InsertVideoTitle(indexPath: indexPath)
}
func InsertVideoTitle(indexPath: IndexPath?)
{
videos.append("Snapchat")
let indexPath = IndexPath(row: videos.count - 1, section: 0)
TableSource.beginUpdates()
TableSource.insertRows(at: [indexPath], with: .automatic)
TableSource.endUpdates()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return videos.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let videoTitle = videos[indexPath.row]
let cell = TableSource.dequeueReusableCell(withIdentifier: "ExpandTVC") as! ExpandTVC
cell.Title.text = videoTitle
cell.ButtonRow.tag = indexPath.row
cell.ButtonRow.setTitle("Rows",for: .normal)
return cell
}
}
This is how my table looks I clicked the Facebook Rows button and it appended the string SnapChat . The Snapchat label should appear in a row below Facebook instead . Any suggestions would be great !
I think the easiest solution without re-writing this whole thing would be adding 1 to the current row of the IndexPath you captured from the action.
let indexPath = TableSource.indexPath(for: cell)
var newIndexPath = indexPath;
newIndexPath.row += 1;
InsertVideoTitle(indexPath: newIndexPath);
I did this from memory because I am not near an IDE, so take a look at the change and apply that change if needed in any other location.
class ExpandController: UIViewController,UITableViewDelegate,UITableViewDataSource {
#IBOutlet weak var TableSource: UITableView!
var videos: [String] = ["FaceBook","Twitter","Instagram"]
override func viewDidLoad() {
super.viewDidLoad()
TableSource.delegate = self
TableSource.dataSource = self
TableSource.tableFooterView = UIView(frame: CGRect.zero)
// Do any additional setup after loading the view.
}
#IBAction func RowClick(_ sender: UIButton) {
guard let cell = sender.superview?.superview as? ExpandTVC else {
return
}
let indexPath = TableSource.indexPath(for: cell)
var newIndexPath = indexPath;
newIndexPath.row += 1;
InsertVideoTitle(indexPath: newIndexPath);
}
func InsertVideoTitle(indexPath: IndexPath?)
{
videos.append("Snapchat")
let indexPath = IndexPath(row: videos.count - 1, section: 0)
TableSource.beginUpdates()
TableSource.insertRows(at: [indexPath], with: .automatic)
TableSource.endUpdates()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return videos.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let videoTitle = videos[indexPath.row]
let cell = TableSource.dequeueReusableCell(withIdentifier: "ExpandTVC") as! ExpandTVC
cell.Title.text = videoTitle
cell.ButtonRow.tag = indexPath.row
cell.ButtonRow.setTitle("Rows",for: .normal)
return cell
}
}
Your current code calls append to add the new item at the end of the array. What you want to do is insert a new row at indexPath.row+1. Array has an insert(element,at:) function.
You have to handle the case where the user has tapped the last row and not add 1 to avoid an array bounds error:
func InsertVideoTitle(indexPath: IndexPath)
{
let targetRow = indexPath.row < videos.endIndex ? indexPath.row+1 : indexPath.row
videos.insert("Snapchat" at:targetRow)
let newIndexPath = IndexPath(row: targetRow, section: 0)
TableSource.beginUpdates()
TableSource.insertRows(at: [newIndexPath], with: .automatic)
TableSource.endUpdates()
}

Leave A Comment With Json Wordpress in Xcode

i made app with Xcode in swift using my Wordpress backend and getting data with json, i can show users comment on my app but i want that users can also leave comments in the app, there should be an option for Leave a comment on post details file, this is my code for showing comments
#IBAction func commentViewController(_ sender: Any) {
let vc = CommentViewController()
vc.dataArray = jsonData["comments"].array
self.navigationController!.pushViewController(vc, animated: true)
}
self.commentButton.layer.borderWidth = 2
self.commentButton.layer.borderColor = baseColor.cgColor
self.commentButton.layer.cornerRadius = 4.0
self.commentButton.tintColor = baseColor
self.commentButton.setTitle("comments(\(jsonData["comments"].array?.count ?? 0))", for: .normal)
but i don't know how to make a comment box where users can also leave comment , thanks
This Is My CommentViewController:
var tableView: UITableView = UITableView()
var dataArray: Array<JSON>!
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Comments"
if #available(iOS 11.0, *) {
navigationController?.navigationBar.prefersLargeTitles = true
navigationController?.navigationItem.largeTitleDisplayMode = .automatic
let attributes = [
NSAttributedString.Key.foregroundColor : navigationBarTextColor, NSAttributedString.Key.font: UIFont(name: "SFUIText-Medium", size: 34),
]
navigationController?.navigationBar.largeTitleTextAttributes = attributes as [NSAttributedString.Key : Any]
} else {
// Fallback on earlier versions
}
// Check if Post have comments
if(self.dataArray.count == 0){
self.view.backgroundColor = UIColor(red: 216 / 255, green: 216 / 255, blue: 216 / 255, alpha: 1.0)
let label = UILabel(frame: CGRect(x: (UIScreen.main.bounds.width/2)-100, y: (UIScreen.main.bounds.height/2)-50, width: 200, height: 50))
label.text = "No Comments"
label.font = UIFont(name: "SFUIText-Regular", size: 18)
label.textAlignment = NSTextAlignment.center
self.view.addSubview(label)
}
else{
self.setupTable()
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func getDateFromString(String:String) -> String{
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let dateObj = dateFormatter.date(from: String)
dateFormatter.dateFormat = "yyyy-MM-dd"
return dateFormatter.string(from: dateObj!)
}
func setupTable(){
tableView = UITableView(frame: UIScreen.main.bounds, style: UITableView.Style.plain)
tableView.delegate = self
tableView.dataSource = self
tableView.register(UINib(nibName: "commentViewCell", bundle: nil), forCellReuseIdentifier: "cell")
tableView.frame.size.height = UIScreen.main.bounds.height - 64
tableView.bounces = false
tableView.allowsSelection = false
self.view.addSubview(self.tableView)
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return self.dataArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! commentViewCell
cell.commentText.text = String(htmlEncodedString: dataArray[indexPath.row]["content"].stringValue)
cell.name.text = String(htmlEncodedString:dataArray[indexPath.row]["name"].stringValue)
cell.date.text = getDateFromString(String: dataArray[indexPath.row]["date"].stringValue)
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
}
So you have a "tableView" field where all comments are shown.
As Joakim Danielson advices, you should add UITextView to the bottom of your screen.
Because the table view can be too long to fit the screen height, it probably will be scrolled, so it's easier to add this text view as a cell.
So you can do this in a following way:
Change the size of tableView for leaving the comment at the end:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return self.dataArray.count + 1
}
Add the cell with text view, let's name it LeaveCommentCell
Return the LeaveCommentCell instance as the last cell:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
if indexPath.row == self.dataArray.count { // this is the last row
let cell = tableView.dequeueReusableCell(withIdentifier: "AddCommentCell", for: indexPath) as! LeaveCommentCell // your new cell
return cell
}
let cell = tableView.dequeueReusableCell(withIdentifier: "ShowCommentCell", for: indexPath) as! commentViewCell // please note identifiers should differ
cell.commentText.text = String(htmlEncodedString: dataArray[indexPath.row]["content"].stringValue)
cell.name.text = String(htmlEncodedString:dataArray[indexPath.row]["name"].stringValue)
cell.date.text = getDateFromString(String: dataArray[indexPath.row]["date"].stringValue)
return cell
}
Add a button (e.g. with text "Post") to LeaveCommentCell, subscribe for event when it's pressed, get comment text and send it to server.

want to select option from dropdown and change title of button according to selected option ...How?

For dropdrawn menu ,i used UItableView and button to display dropdown list when i select option from dropdown i want to change title of button according to selected option ??
// foodbutton click
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "foodcell", for: indexPath)
// cell.textLabel?.text = array [indexPath.row]
cell.textLabel?.text = array [indexPath.row]
return cell
}
#nonobjc func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
let cell = tableView.cellForRow(at: indexPath)
selectFoodbutton.setTitle(cell?.textLabel?.text, for: .normal)
self.foodtable.isHidden = true
}
#IBAction func selectFoodbutton(_ sender: Any) {
self.foodtable.isHidden = !self.foodtable.isHidden
}
In button action write the code for appear the table view like below way.
First u create a tableview below that button.
load datasource into that tableview.
then select the one of the cell.
then set the button title as selected one.
then finally hide the table view.
code snippet like this
#IBAction func educationBtnAction(_ sender: AnyObject) {
// let point = textfield.getBottomTableViewPoint()
let point = sender.getPointBased(level: 1)
self.educationTableview = UITableView(frame: CGRect(x: point.x, y: point.y, width: sender.frame.size.width + 10, height: 150), style: .plain)
self.educationTableview.dataSource = self
self.educationTableview.delegate = self
self.educationTableview.backgroundColor = UIColor.clear
self.educationTableview.applyPropertiesToPopupTableView()
// textfield.superview?.addSubview(labPanelTableView)
bgScrollView.addSubview(educationTableview)
if self.educationTableview.alpha == 0.0{
UIView.animate(withDuration: 0.5, delay: 0.0, options: .curveEaseOut, animations: {
self.hidePopups()
self.educationTableview.alpha = 1.0
}, completion: { finished in
})
}
commonTypeArray = ["1", "2", "3", "4", "5",]
self.educationTableview.reloadData()
}
func hidePopups() {
self.educationTableview.alpha = 0.0
}
For remaining process your code above in question is enough

Value of type '_' has no member

In the cb.check(self.rowChecked[indexPath.row]) line under cellForRowAt I'm getting a "Value of type 'LolFirstTableViewController' has no member 'rowChecked'" even though I set up rowChecked to be an array of Booleans with tasks.count number of items. Do I need to initialize rowChecked somewhere else besides cellForRowAt or what am I doing wrong here? The point of this code is to make a checkbox show up in each cell of a table where you can click it to change the accessory to a check mark, and click it again to uncheck it. The check box itself is a separate custom class called CheckButton. I'm still learning Swift so any help would be greatly appreciated! Thank you!
import UIKit
class LoLFirstTableViewController: UITableViewController {
var tasks:[Task] = taskData
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 60.0
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tasks.count
}
#IBAction func cancelToLoLFirstTableViewController(_ segue:UIStoryboardSegue) {
}
#IBAction func saveAddTask(_ segue:UIStoryboardSegue) {
if let AddTaskTableViewController = segue.source as? AddTaskTableViewController {
if let task = AddTaskTableViewController.task {
tasks.append(task)
let indexPath = IndexPath(row: tasks.count-1, section: 0)
tableView.insertRows(at: [indexPath], with: .automatic)
}
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TaskCell", for: indexPath) as! TaskCell
let task = tasks[indexPath.row]
cell.task = task
var rowChecked: [Bool] = Array(repeating: false, count: tasks.count)
if cell.accessoryView == nil {
let cb = CheckButton()
cb.addTarget(self, action: #selector(buttonTapped(_:forEvent:)), for: .touchUpInside)
cell.accessoryView = cb
}
let cb = cell.accessoryView as! CheckButton
cb.check(self.rowChecked[indexPath.row])
return cell
}
func buttonTapped(_ target:UIButton, forEvent event: UIEvent) {
guard let touch = event.allTouches?.first else { return }
let point = touch.location(in: self.tableView)
let indexPath = self.tableView.indexPathForRow(at: point)
var tappedItem = tasks[indexPath!.row] as Task
tappedItem.completed = !tappedItem.completed
tasks[indexPath!.row] = tappedItem
tableView.reloadRows(at: [indexPath!], with: UITableViewRowAnimation.none)
}
You are declaring rowChecked as a local variable and calling it with self.rowChecked as if it were a class property.
To solve this issue, remove the self. before rowChecked.
Old:
cb.check(self.rowChecked[indexPath.row])
New:
cb.check(rowChecked[indexPath.row])
There might be further issues, but that's the reason for the error as your code currently stands.
You have the line: var rowChecked: [Bool] = Array(repeating: false, count: tasks.count) inside the tableView:cellForRowAt method, so it's a local variable, it's not a property of the LolFirstTableViewController class.
That means you need to change this line: cb.check(self.rowChecked[indexPath.row]) to cb.check(rowChecked[indexPath.row]) (Removed self.).

Resources