How to apply filter based on multiple selected rows in UITableView using swift 3 - uitableview

Hello all m having multisectioned tableview design like
want to apply filter based on the selected rows in which all the selection is in OR condition except the searchcriteria section(this section is mandatory),now what i want to achieve is want to save all the selection and filter the data when user clicks on Apply button.How to achieve this.Please help.
note:i dont want to use any database coz in future i have to post all the selected values using POST method.
Code :
ViewController.swift
import UIKit
class ViewController: UIViewController,ExpandableHeaderViewDelegate,UITableViewDelegate,UITableViewDataSource {
#IBOutlet weak var tableview: UITableView!
var sections = [
Section(sectionname: "Year" ,
cellnames: ["2017-2018","2016-2017","2015-2016"],
expanded: false,
subtitle: "Please select a Year"),
Section(sectionname: "School",
cellnames: ["School A","School B","School C"],
expanded: false,
subtitle: "Please select a School"),
Section(sectionname: "SearchCriteria",
cellnames: ["No of Students","No of Student on RTE","No of Differently Abled Students","No of Student Opted For School Transport"],
expanded: false,
subtitle: "Please select your SearchCriteria"),
Section(sectionname: "Class",
cellnames: ["IX","X","XI","XII"],
expanded: false,
subtitle: "Please select a Class"),
Section(sectionname: "Section",
cellnames: ["A","B","C","D","E"],
expanded: false,
subtitle: "Please Select a Section")
]
var selectIndexPath : IndexPath!
override func viewDidLoad() {
super.viewDidLoad()
self.tableview.allowsMultipleSelection = true
selectIndexPath = IndexPath(row: -1, section: -1)
let nib = UINib(nibName: "ExpandableHeaderView", bundle: nil)
tableview.register(nib, forHeaderFooterViewReuseIdentifier: "expandableHeaderView")
// Do any additional setup after loading the view, typically from a nib.
}
func numberOfSections(in tableView: UITableView) -> Int {
return sections.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return sections[section].cellnames.count
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 44
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if (sections[indexPath.section].expanded)
{
return 44
}
else
{
return 0
}
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 2
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerview = tableview.dequeueReusableHeaderFooterView(withIdentifier: "expandableHeaderView") as! ExpandableHeaderView
headerview.customInit(title: sections[section].sectionname, subtitle: sections[section].subtitle, section: section, delegate: self)
return headerview
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableview.dequeueReusableCell(withIdentifier: "labelcell")
cell?.textLabel?.text = sections[indexPath.section].cellnames[indexPath.row]
cell?.accessoryType = (indexPath == selectIndexPath) ? .checkmark : .none
return cell!
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.selectIndexPath = indexPath
self.sections[indexPath.section].subtitle = (tableview.cellForRow(at: indexPath)?.textLabel?.text)!
sections[indexPath.section].expanded = !sections[indexPath.section].expanded
tableview.beginUpdates()
tableview.reloadSections([indexPath.section], with: .automatic)
tableview.endUpdates()
}
func toggleSection(header:ExpandableHeaderView,section : Int)
{
sections[section].expanded = !sections[section].expanded
tableview.beginUpdates()
for i in 0 ..< sections[section].cellnames.count {
tableview.reloadRows(at: [IndexPath(row: i, section: section)], with: .automatic)
}
tableview.endUpdates()
}
#IBAction func done_action(_ sender: Any) {
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
ExpandableHeaderView.xib
ExpandableHeaderView.swift
import UIKit
protocol ExpandableHeaderViewDelegate {
func toggleSection(header:ExpandableHeaderView,section:Int)
}
class ExpandableHeaderView: UITableViewHeaderFooterView {
var delegate :ExpandableHeaderViewDelegate?
var section : Int!
#IBOutlet weak var TitleLabel: UILabel!
#IBOutlet weak var SubTitleLabel: UILabel!
override init(reuseIdentifier: String?) {
super.init(reuseIdentifier: reuseIdentifier)
self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(selectHeaderView)))
}
required init?(coder aDecoder: NSCoder) {
super.init(coder : aDecoder )
self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(selectHeaderView)))
}
func selectHeaderView(gesture:UITapGestureRecognizer)
{
let cell = gesture.view as! ExpandableHeaderView
delegate?.toggleSection(header: self, section: cell.section)
}
func customInit(title:String,subtitle : String,section:Int,delegate:ExpandableHeaderViewDelegate)
{
self.TitleLabel.text = title
self.SubTitleLabel.text = subtitle
self.section = section
self.delegate = delegate
}
override func layoutSubviews() {
super.layoutSubviews()
self.TitleLabel?.textColor = UIColor.white
self.SubTitleLabel?.textColor = UIColor.white
self.SubTitleLabel?.alpha = 0.7
self.contentView.backgroundColor = UIColor.darkGray
}
}
Section.swift
import Foundation
struct Section
{
var sectionname : String!
var cellnames : [String]!
var expanded : Bool!
var subtitle : String!
init(sectionname:String,cellnames : [String],expanded : Bool,subtitle : String)
{
self.sectionname = sectionname
self.cellnames = cellnames
self.expanded = expanded
self.subtitle = subtitle
}
}
Please Help.I googled a lot but cant find the soultion of my scenario.

Related

Swift 5 - Set TextLabel in Custom CollectionviewCell from JSON Array

I have created a custom cell for my collectionview that i have set in a tableview for my app. I need to know to to set the text label to appear as the items in my array that is listed in my JSON File that is local.
View Controller:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var workoutData = [Models]()
#IBOutlet weak var tableview: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
parseJSON()
tableview.register(CollectionTableViewCell.nib(), forCellReuseIdentifier: CollectionTableViewCell.identifier)
print(workoutData)
}
func numberOfSections(in tableView: UITableView) -> Int {
return workoutData.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return workoutData[section].title
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return workoutData[section].workouts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: CollectionTableViewCell.identifier, for: indexPath) as! CollectionTableViewCell
cell.configure(with: workoutData)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableview.deselectRow(at: indexPath, animated: true)
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 250.0
}
func parseJSON() {
let url = Bundle.main.url(forResource: "data", withExtension: "json")!
do{
let data = try Data(contentsOf: url)
workoutData = try JSONDecoder().decode([Models].self, from: data)
} catch {
print(error)
}
}
}
My Custom Cell File:
import UIKit
class MyCollectionViewCell: UICollectionViewCell {
var workoutData = [Models]()
#IBOutlet weak var myLabel: UILabel!
static let identifier = "MyCollectionViewCell"
static func nib() -> UINib {
return UINib(nibName: "MyCollectionViewCell", bundle: nil)
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
public func configure(with model: Models) {
self.myLabel.text = //what to put here.
print(model.title)
}
}
My JSON File:
[
{
"title": "Chest",
"workouts": [
"Bench",
"Pushup",
"Incline Press",
"Decline Press",
]
},
{
"title": "Back",
"workouts": [
"Barbell Row",
"Lat Pulldown",
"Deadlift",
"Back Extension",
]
},
{
"title": "Arms",
"workouts": [
"Barbell Curl",
"Dumbbell Curl",
"Tricep Pressdown",
"Skull Crusher",
]
}
]
I want my text label to show the items in my workouts array. when i set it i get the error "cannot assign value of type '[String]' to type 'String'". I would appreciate any help or directions. Thanks
EDIT:
I am looking to build my layout similar to the horizontal scroll of the the app store
workouts is an array of String. So firstly you need to get the String from array by index.
You can use this to show the first value on the label
self.myLabel.text = models.workouts[0]
Or If you want to show all the workouts values on the array then you can use
self.myLabel.text = models.workouts.joined(separator: ", ")

UITableViewCell multiple select circle (Edit Control) coming randomly

I created a ViewController with a UITableView as a subView.
import UIKit
class ViewController: UIViewController {
private var tableDataSource = [
"Lorem Ipsum is simply du.",
"It is a long established .",
"Lorem Ipsum come",
"All the Lorem .",
"The standard ch.",
"The generated.",
"Various versions."
]
private var isReorderingEnabled = false
private var isDeleteEnabled = false
#IBOutlet private var reorderCellsBarButton: UIBarButtonItem!
#IBOutlet private var selectCellsBarButton: UIBarButtonItem! {
didSet {
selectCellsBarButton.tag = ButtonTags.Select
}
}
#IBOutlet private var deleteCellsBarButton: UIBarButtonItem! {
didSet {
deleteCellsBarButton.tag = ButtonTags.Delete
}
}
#IBOutlet weak private var tableView: UITableView! {
didSet {
tableView.dataSource = self
tableView.delegate = self
tableView.allowsMultipleSelectionDuringEditing = false
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 300
}
}
}
extension ViewController {
private struct ButtonTags {
static let Delete = 2
static let Select = 1
}
private struct LocalizedStrings {
static let EnableReorderingText = "Reorder"
static let DisableReorderingText = "Done"
static let EnableSelectionText = "Select"
static let ConfirmDeletionText = "Delete"
static let DisableDeletionText = "Cancel"
}
}
extension ViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
setDeleteBarButton(hidden: true, animated: false)
}
}
// IBActions
extension ViewController {
#IBAction private func reorderCells(_ sender: UIBarButtonItem) {
isReorderingEnabled = !tableView.isEditing
setSelectBarButton(hidden: isReorderingEnabled)
sender.title = isReorderingEnabled ? LocalizedStrings.DisableReorderingText : LocalizedStrings.EnableReorderingText
tableView.setEditing(isReorderingEnabled, animated: true)
tableView.reloadData()
}
#IBAction private func deleteCells(_ sender: UIBarButtonItem) {
isDeleteEnabled = !tableView.isEditing
setDeleteBarButton(hidden: !isDeleteEnabled)
selectCellsBarButton.title = isDeleteEnabled ? LocalizedStrings.DisableDeletionText : LocalizedStrings.EnableSelectionText
if sender.tag == ButtonTags.Delete {
deleteSelectedRows()
}
tableView.allowsMultipleSelectionDuringEditing = isDeleteEnabled
tableView.setEditing(isDeleteEnabled, animated: true)
tableView.reloadData()
}
}
// Custom Helper methods
extension ViewController {
private func setDeleteBarButton(hidden: Bool, animated: Bool = true) {
navigationItem.setRightBarButtonItems([(hidden ? reorderCellsBarButton : deleteCellsBarButton)], animated: animated)
}
private func setSelectBarButton(hidden: Bool, animated: Bool = true) {
self.navigationItem.setLeftBarButton((hidden ? nil : selectCellsBarButton), animated: animated)
}
private func deleteSelectedRows() {
guard let selectedRows = tableView.indexPathsForSelectedRows else { return }
let indexes = selectedRows.map { $0.row }
tableDataSource.remove(indexes: indexes)
tableView.deleteRows(at: selectedRows, with: .fade)
}
}
extension ViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableDataSource.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let customCell = tableView.dequeueReusableCell(withIdentifier: CustomTableViewCell.identifier, for: indexPath) as! CustomTableViewCell
customCell.setup(content: tableDataSource[indexPath.row], for : indexPath.row)
return customCell
}
}
// pragma - To Select/Edit/Move TableView Cells
extension ViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
tableDataSource.move(from: sourceIndexPath.row, to: destinationIndexPath.row)
let reloadingIndexPaths = IndexPath.createForNumbers(from: sourceIndexPath.row, to: destinationIndexPath.row)
DispatchQueue.main.async {
tableView.reloadRows(at: reloadingIndexPaths, with: .none)
}
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
tableDataSource.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .none)
}
}
}
// pragma - Settings for Edit/Move TableViewCell
extension ViewController {
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
print("Edit- \(tableView.isEditing)")
return tableView.isEditing
}
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
print("Move- \(isReorderingEnabled)")
return isReorderingEnabled
}
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
print("Style- None")
return .none
}
func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
print("indent- \(isDeleteEnabled)")
return isDeleteEnabled
}
}
In this, I have made three bar buttons,one for Reordering , and other two for Deletion and Cancellation.
So, for delete I have provided ability to select multiple rows.
But the problem is, when Reordering selected, the checkbox is still appearing(Not clickable though). And sometimes when Deletion selected, checkbox doesn't appear.
Cannot understand the absurd behaviour. Is this a bug of XCode ? Please help.
Added Content:
CustomTableViewCell class :
import UIKit
class CustomTableViewCell: UITableViewCell {
static let identifier = "customCellIdentifier"
#IBOutlet weak private var titleLabel: UILabel!
#IBOutlet weak private var backgroundImageView: UIImageView!
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
let selectionView = UIView()
selectionView.backgroundColor = UIColor.clear
selectedBackgroundView = selectionView
}
}
extension CustomTableViewCell {
func setup(content: String, for rowNumber: Int) {
titleLabel.text = content
let backgroundImageName = rowNumber % 2 == 0 ? ImageAssetNames.BlueMatte : ImageAssetNames.GreenThreads
backgroundView = UIImageView(image: UIImage(named: backgroundImageName))
}
}

Expandable listview not collapsing in swift

I'm going through this tutorial (https://github.com/jeantimex/ios-swift-collapsible-table-section) trying to build an expandable listview into my application. The only differance between my code and the tutorials is I'm doing it with a storyboard.
I seem to have it almost fully functional but I have one problem. The rows are collapsing and then are repopulating without being clicked a second time. I've gone through my code multiple times but I can't seem to find the problem.
Here is my code:
List View Controller Class:
import UIKit
class ItemListViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var sections = [Item]()
#IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
sections = [
Item(name: "Mac", items: ["MacBook", "MacBook Air", "MacBook Pro", "iMac", "Mac Pro", "Mac mini", "Accessories", "OS X El Capitan"]),
Item(name: "iPad", items: ["iPad Pro", "iPad Air 2", "iPad mini 4", "Accessories"]),
Item(name: "iPhone", items: ["iPhone 6s", "iPhone 6", "iPhone SE", "Accessories"])
]
tableView.delegate = self
tableView.dataSource = self
}
func numberOfSections(in tableView: UITableView) -> Int {
return sections.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return sections[section].items.count
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 44
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Table view cells are reused and should be dequeued using a cell identifier.
let cellIdentifier = "ItemTableViewCell"
guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? ItemTableViewCell else {
fatalError("The dequeued cell is not an instance of ItemTableViewCell.")
}
cell.itemLabel.text = sections[indexPath.section].items[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerCellIdentifier = "ItemHeaderTableViewCell"
let headerCell = tableView.dequeueReusableCell(withIdentifier: headerCellIdentifier) as! ItemHeaderTableViewCell
headerCell.itemHeaderLabel.text = sections[section].name
headerCell.setCollapsed(sections[section].collapsed)
headerCell.section = section
headerCell.delegate = self
return headerCell
}
}
extension ItemListViewController: ItemHeaderTableViewCellDelegate {
func toggleSection(_ header: ItemHeaderTableViewCell, section: Int) {
let collapsed = !sections[section].collapsed
// Toggle collapse
sections[section].collapsed = collapsed
header.setCollapsed(collapsed)
// Adjust the height of the rows inside the section
tableView.beginUpdates()
for i in 0 ..< sections[section].items.count {
let indexPath = IndexPath(item: i, section: 0)
tableView.reloadRows(at: [indexPath], with: .top)
}
tableView.endUpdates()
}
}
Item Header Table View Cell Class:
import UIKit
protocol ItemHeaderTableViewCellDelegate {
func toggleSection(_ header: ItemHeaderTableViewCell, section: Int)
}
class ItemHeaderTableViewCell: UITableViewCell {
var delegate: ItemHeaderTableViewCellDelegate?
var section: Int = 0
#IBOutlet var itemHeaderLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(ItemHeaderTableViewCell.tapHeader(_:))))
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func tapHeader(_ gestureRecognizer: UITapGestureRecognizer) {
guard let cell = gestureRecognizer.view as? ItemHeaderTableViewCell else {
return
}
delegate?.toggleSection(self, section: cell.section)
}
func setCollapsed(_ collapsed: Bool) {
// Animate the arrow rotation (see Extensions.swf)
// arrowLabel.rotate(collapsed ? 0.0 : CGFloat(M_PI_2))
}
}
Item Table View Cell:
import UIKit
class ItemTableViewCell: UITableViewCell {
#IBOutlet var itemLabel: 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
}
}
Item class:
import UIKit
class Item {
var name: String!
var items: [String]!
var collapsed: Bool!
init(name: String, items: [String], collapsed: Bool = false) {
self.name = name
self.items = items
self.collapsed = collapsed
}
}
So why are my cells repopulating when I try to collapse them? Any help is appreciated. Thanks!
It looks like you're missing the function that actually shows/hides the rows:
// from the GitHub repo you linked to:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return sections[(indexPath as NSIndexPath).section].collapsed! ? 0 : 44.0
}
If you are using storyboard, I have a repository for Expandable UITableView you can check it out, if it works for you.
https://github.com/PriyamDutta/PDExpandable

Infinite scroll with UITableView and an Array

I'm new in Swift and I want to make an infinite scroll with an Array. Here it's my class TableViewController
class TableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var legumes: [String] = ["Eggs", "Milk", "Chocolat", "Web", "Miel", "Pop", "Eco", "Moutarde", "Mayo", "Thea", "Pomelade", "Gear", "Etc" , "Nop", "Dews", "Tout", "Fun", "Xen" , "Yoga" ]
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.delegate = self
self.tableView.dataSource = self
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.legumes.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! ImageTableViewCell
return cell
}
}
I want to show the first ten items of my array and when I am on the bottom of the TableViewController, it will load the next ten items, etc. I don't know how to do, I see a lot of code on GitHub but I don't know how to implement them.
Thank you so much.
Consider using PagingTableView
class MainViewController: UIViewController {
#IBOutlet weak var contentTable: PagingTableView!
var legumes: [String] = ["Eggs", "Milk", "Chocolat", "Web", "Miel", "Pop", "Eco", "Moutarde", "Mayo", "Thea", "Pomelade", "Gear", "Etc" , "Nop", "Dews", "Tout", "Fun", "Xen" , "Yoga" ]
override func viewDidLoad() {
super.viewDidLoad()
contentTable.dataSource = self
contentTable.pagingDelegate = self
}
}
extension MainViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return legumes.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! ImageTableViewCell
guard legumes.indices.contains(indexPath.row) else { return cell }
cell.content = legumes[indexPath.row]
return cell
}
}
extension MainViewController: PagingTableViewDelegate {
func paginate(_ tableView: PagingTableView, to page: Int) {
contentTable.isLoading = true
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.legumes.append(contentsOf: legumes)
self.contentTable.isLoading = false
}
}
}
Modify the paginate function to work as you wish
What you're describing is called pagination. You should do something like this:
/* Number of page you're loading contents from */
var pageIndex: Int = 1
override func scrollViewDidScroll(scrollView: UIScrollView) {
let offsetY = scrollView.contentOffset.y
let contentHeight = scrollView.contentSize.height
if offsetY > contentHeight - scrollView.frame.size.height {
/* increment page index to load new data set from */
pageIndex += 1
/* call API to load data from next page or just add dummy data to your datasource */
/* Needs to be implemented */
loadNewItemsFrom(pageIndex)
/* reload tableview with new data */
tableView.reloadData()
}
}

Load more options with UITableView

Trying to load my data in page using pagination, I've already seen many examples but all are in Objective-C and some questions are unanswered.
My code:
class testTableViewController: UITableViewController {
//MARK: - Properties -
var allObjectArray: NSMutableArray = []
var elements: NSMutableArray = []
var currentPage = 0 //number of current page
var nextpage = 0
var selectedRow = Int()
//MARK: - View Life Cycle -
override func viewDidLoad() {
super.viewDidLoad()
for var i = 1; i < 500; i++ {
allObjectArray.addObject(i)
}
elements.addObjectsFromArray(allObjectArray.subarrayWithRange(NSMakeRange(0, 30)))
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: - Table view data source -
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return elements.count + 1
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
selectedRow = (tableView.indexPathForSelectedRow?.row)!
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var customCell = tableView.dequeueReusableCellWithIdentifier("cell")
customCell = UITableViewCell(style: .Default, reuseIdentifier: "cell")
customCell!.textLabel!.text = "cell - \(allObjectArray[indexPath.row])"
if indexPath.row == elements.count {
customCell?.textLabel?.textColor = UIColor.blueColor()
customCell?.textLabel?.text = "Load more..."
}
return customCell!
}
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
nextpage = elements.count
if indexPath.row == nextpage {
if indexPath.row == selectedRow {
currentPage++
nextpage = elements.count - 5
elements.addObjectsFromArray(allObjectArray.subarrayWithRange(NSMakeRange(currentPage, 30)))
tableView.reloadData()
}
}
}
}
I want this kind of output:
Tried to fetch selected index but it will return nil.
Create Outlets in Interface Builder for tableview and make two dynamic prototype cells give them identifiers make one cell with a button(your load more cell button)
Then create action with that button that will contain the logic to load more cells!!!
now see the snipet below for reference...
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
#IBOutlet weak var tblDemo: UITableView!
var arForCells:NSMutableArray = NSMutableArray()
let simpleCellID = "SimpleCell"
let loadMoreCell = "LoadMoreCell"
override func viewDidLoad() {
super.viewDidLoad()
tblDemo.delegate = self
tblDemo.dataSource = self
arForCells = NSMutableArray(objects: "1", "2", "3", "4", "5", "6", "7", "8", "9", "10")
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arForCells.count + 1
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if (indexPath.row == arForCells.count){
let cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier(loadMoreCell, forIndexPath: indexPath)
return cell
}else {
let cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier(simpleCellID, forIndexPath: indexPath)
let lblCounter = cell.viewWithTag(111) as! UILabel
lblCounter.text = arForCells.objectAtIndex(indexPath.row) as! String
return cell
}
}
#IBAction func loadMoreCells(sender: AnyObject) {
let newAr:NSArray = NSArray(objects: "1", "2", "3", "4", "5", "6", "7", "8", "9", "10")
arForCells.addObjectsFromArray(newAr as [AnyObject])
tblDemo.reloadData()
}}
as I have checked, It should give you the desired results.
You could also do the same in TableViewFooter.
To set "Load More.." text add a label with this text in a view having the same size of your tableViewCell. Then add this in your tableView footer. Add a (custom/transparent)button in footer view so when that touched it will load your main array with more data and then reload your tableView.
Hope this helps!
First of all, You don't have to use this:
selectedRow = (tableView.indexPathForSelectedRow?.row)!
in the didSelectRowAtIndexPath. You can use simply
selectedRow = indexPath.row
next, your logic for willDisplayCellAtIndexPath seems redundant if you want to have cell to tap on it. You can simply put the following in enter code here:
nextpage = elements.count
if indexPath.row == nextpage {
currentPage++
nextpage = elements.count - 5
elements.addObjectsFromArray(allObjectArray.subarrayWithRange(NSMakeRange(currentPage, 30)))
tableView.reloadData()
}
also, I am not sure why do you need nextpage = elements.count - 5 but I assume that you have reason behind this.
done it my self
import UIKit
class LoadMoreTableVC: UITableViewController {
//MARK: - Properties -
var allObjectArray: NSMutableArray = []
var elements: NSMutableArray = []
var currentPage = 0 //number of current page
var nextpage = 0
var totalElements = 500 //total elements
var elementAtOnePage = 30 //at one page
//MARK: - View Life Cycle -
override func viewDidLoad() {
super.viewDidLoad()
for i in 0 ..< totalElements {
allObjectArray.addObject(i+1)
}
elements.addObjectsFromArray(allObjectArray.subarrayWithRange(NSMakeRange(0, elementAtOnePage)))
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: - Table view data source -
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let count = elements.count + 1
if count < allObjectArray.count
{
return count
}
else
{
return allObjectArray.count
}
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.row == elements.count {
loadDataDelayed()
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
cell.textLabel!.text = "\(allObjectArray[indexPath.row])"
if indexPath.row == elements.count {
cell.textLabel?.text = "Load more..."
}
return cell
}
func loadDataDelayed(){
currentPage += 1
elements.addObjectsFromArray(allObjectArray.subarrayWithRange(NSMakeRange(currentPage, elementAtOnePage)))
tableView.reloadData()
}
}
I have already done this is in swift.
func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
if loading == true {
var endScrolling:CGFloat = scrollView.contentOffset.y + scrollView.frame.size.height
if(endScrolling >= scrollView.contentSize.height){
NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, selector: "loadDataDelayed", userInfo: nil, repeats: false)
}
}
}
Please try this code.
And share your response.
Happy coding :)

Resources