UITableView is reloaded when presentviewcontroller or pushviewcontroller - uitableview

I have a uitableview with some complex cells,
If I do presentviewcontroller or pushviewcontroller when I press the button in the cell,
it will reload data automatically,
how can i stop it?
this is the base Controller
import UIKit
class Controller: UIViewController{
override func viewDidLoad() {
super.viewDidLoad();
initView();
}
func initView(){
self.view.backgroundColor = UIColor.whiteColor();
}
override func preferredStatusBarStyle() -> UIStatusBarStyle {
return UIStatusBarStyle.LightContent;
}
}
and this is the second level
import Foundation
class LoadableController: Controller {
var requestNum : Int = 0;
func loadData(complete: (()->Void)? = nil){
self.requestComplete();
}
func requestComplete(){
if(self.requestNum == 0){
requestFinished();
return;
}
self.requestNum = self.requestNum > 0 ? self.requestNum - 1 : 0;
if(self.requestNum == 0){
requestFinished();
}
}
func requestFinished(){}
}
this is the third level
class TableListViewController: LoadableController, UITableViewDelegate, UITableViewDataSource {
var tableView : UITableView?;
var curPage : Int = 0;
var totalPage : Int = 0;
override func viewDidLoad() {
super.viewDidLoad()
}
override func initView() {
super.initView();
tableView = UITableView();
tableView!.delegate = self;
tableView!.dataSource = self;
tableView!.delaysContentTouches = false;
tableView!.canCancelContentTouches = true;
self.view.addSubview(tableView!);
tableView!.snp_makeConstraints { [unowned self](make) in
make.edges.equalTo(self.view);
}
let header = EGRefresh(refreshingTarget: self, refreshingAction: #selector(self.loadData));
header.setImages(Global.LOADING_IMAGES, duration: 0.16, forState: .Idle);
header.setImages(Global.LOADING_IMAGES, duration: 0.16, forState: .Pulling);
header.setImages(Global.LOADING_IMAGES, duration: 0.16, forState: .WillRefresh);
header.setImages(Global.LOADING_IMAGES, duration: 0.16, forState: .Refreshing);
header.lastUpdatedTimeLabel.hidden = true;
tableView!.mj_header = header;
let footer = MJRefreshBackNormalFooter.init(refreshingTarget: self, refreshingAction: #selector(self.loadNext));
tableView!.mj_footer = footer;
}
func loadNext(){
tableView!.mj_footer.endRefreshing();
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("ListCell", forIndexPath: indexPath);
return cell;
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1;
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1;
}
override func requestFinished() {
tableView!.mj_header.endRefreshing();
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
deinit{
DDLogInfo("TableListViewController deinit");
}
}
and here is the place where the tableview reload automatically.
import UIKit
class CircleViewController: TableListViewController {
override func viewDidLoad() {
super.viewDidLoad();
}
override func initView(){
super.initView();
self.title = "Circle";
let items = ["One", "Two"];
let segment = UISegmentedControl(items: items);
segment.selectedSegmentIndex = 0;
segment.setWidth(80, forSegmentAtIndex: 0);
segment.setWidth(80, forSegmentAtIndex: 1);
self.navigationItem.titleView = segment;
tableView!.estimatedRowHeight = 50;
tableView!.rowHeight = UITableViewAutomaticDimension;
// tableView!.contentInset = UIEdgeInsetsMake(Dimens.TopBarHeight, 0, 0, 0);
tableView!.registerClass(TextOnlyCell.self, forCellReuseIdentifier: "CircleTextOnlyCell");
tableView!.registerClass(ImageAndPageCell.self, forCellReuseIdentifier: "CircleImageAndPageCell");
Event.addEventListener(self, selector: #selector(self.goComment(_:)), name: EventType.CIRCLE_COMMENT, object: nil);
}
func goComment(ns: NSNotification) {
let commentView = PostCommentViewController();
self.navigationController?.pushViewController(commentView, animated: true);
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension;
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10;
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true);
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1;
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("CircleImageAndPageCell", forIndexPath: indexPath) as? ImageAndPageCell;
if cell == nil {
cell = ImageAndPageCell.init(style: .Default, reuseIdentifier: "CircleImageAndPageCell");
}
let images = [UIImage(named: "b.jpg")!, UIImage(named: "a.jpg")!, UIImage(named: "c.jpg")!, UIImage(named: "a.jpg")!];
cell?.initView(nil, nickname: "im a nickname", time: "10 min", content: NSMutableAttributedString(string: "asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdf"), likeNum: 10, commentNum: 12, shareNum: 13, totalLine: 20, images: images, cellIndex: indexPath.row, hasPage: true, pageIcon: UIImage(named: "c.jpg")!, titleStr: "ahahaha");
return cell!;
}
override func loadData(complete: (() -> Void)?) {
self.requestComplete();
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
deinit {
Event.removeAllEventListener(self);
DDLogInfo("CircleViewController deinit");
}
}
If goComment be called,
the viewcontroller will be pushed,
then the tableview will jump to top,
I add a break point to the cellForRowAtIndexPath,
it's called.
then I tried the presentviewcontroller,
this problem also happened,
even though I did presentviewcontroller in the outside viewcontroller.
it seems not reload data,
it's just scrolls to the top.

it's looking like table view not taking the uitoolbar size(44 points) in account
Save the tableview offset in prepareForSegue: (save it in a CGPoint property)
self.tableViewScrollOffset = self.tableView.contentOffset;
Then, in viewWillAppear:, check if it has been modified. If so, restore it.
if(self.tableView.contentOffset.y != self.tableViewScrollOffset.y) {
[self.tableView setContentOffset:self.tableViewScrollOffset];
self.tableViewScrollOffset = CGPointZero;
}

Related

How to hide UILabel Swift: Label is creating space in table view controller when Label is set to hidden

I am trying to hide a UILabel..!
I have taken a table view controller in storyboard which contains UIlabel,TableView & Segmented Control.
I have two categories one is Data & Empty data.
When user clicks on Data -> data should appear in TableView & Label should hide.
When user clicks on Empty -> data should hide & label should appear.
I could do that... But Label is doing a problem here (It is creating a gap)
Problem:
Label is creating a gap on top of table view when there is data.
Question:
How to remove label when it is hidden.
I want to display the label at the center of the view(user friendly).
ScreenShots:
Simulator:
Code:
// MARK: - Properties
let sectionHeaders = ["One","Two"];
var rowValues = [["First","Second","Three"],["four","five","six"]];
// MARK: - IBOutlets
#IBOutlet weak var noDataLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Table View"
noDataLabel.isHidden = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
if (rowValues.isEmpty) {
return 0
} else {
return sectionHeaders.count
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if (rowValues.isEmpty) {
return 0
} else {
return rowValues[section].count
}
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return sectionHeaders[section]
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = rowValues[indexPath.section][indexPath.row];
return cell
}
// MARK: - IBActions
#IBAction func segmentButtonPressed(_ sender: UISegmentedControl) {
if sender.selectedSegmentIndex == 0 {
if rowValues.isEmpty {
noDataLabel.isHidden = true
rowValues = [["First","Second","Three"],["four","five","six"]];
}
} else {
rowValues.removeAll()
noDataLabel.isHidden = false
}
tableView.reloadData()
}
You can change the UILabel frame height as shown below that will solve your problem.
func editLabelHeight(edit: Bool) {
if edit {
var labelFrame = noDataLabel.frame
labelFrame.size.height = 0
noDataLabel.frame = labelFrame
}
else {
var labelFrame = noDataLabel.frame
labelFrame.size.height = 44
noDataLabel.frame = labelFrame
}
}
In your viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
editLabelHeight(edit: true)
}
In IBAction
#IBAction func segmentButtonPressed(_ sender: UISegmentedControl) {
if sender.selectedSegmentIndex == 0 {
if rowValues.isEmpty {
noDataLabel.isHidden = true
editLabelHeight(edit: true)
rowValues = [["First","Second","Three"],["four","five","six"]]
}
} else {
rowValues.removeAll()
editLabelHeight(edit: false)
noDataLabel.isHidden = false
}
tableView.reloadData()
}

Getting Crash in cellForRowAtIndexPath in tableView on Crashlytics

I got weird crash on Crashlytics, It's showing crash in the line as commented in code.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.row >= collectionArrayApiObject.collectionsArray.count {
return UITableViewCell(frame: CGRectZero)
}
var tableViewCell:CollectionsTableViewCell? = tableView.dequeueReusableCellWithIdentifier("collectionsCell") as? CollectionsTableViewCell
if (tableViewCell == nil) {
tableViewCell = CollectionsTableViewCell(style: .Default, reuseIdentifier: "collectionsCell")
}
// Got crash in below line
let collectionObject = collectionArrayApiObject.collectionsArray[indexPath.row]
tableViewCell!.setCollection(collectionObject)
return tableViewCell!
}
This is the stack trace that I got..
But not getting why this even happened? I have already put check that
index.row >= collectionArrayApiObject.collectionsArray.count
so it should not be index out of range case. Can any one give me just one case in which this can happen?
NOTE: This happened with only one user till now but still why this even happened?
Whole Table View Controller:
import UIKit
class CollectionsViewController: CUIBaseViewController, CollectionArrayApiObjectDelegate, UITableViewDataSource, UITableViewDelegate, UIViewControllerPreviewingDelegate {
var collectionsTableView : UITableView?
var collectionArrayApiObject : CollectionArrayApiObject = CollectionArrayApiObject()
var headerSearchButton : UIBarButtonItem?
var cityId: String?
required init?(coder aDecoder: NSCoder) {
fatalError("NSCoding not supported")
}
override init(nibName nibNameOrNil: String!, bundle nibBundleOrNil: NSBundle!) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
convenience init(CityId: String? = nil) {
self.init(nibName: nil, bundle: nil)
self.cityId = CityId
self.view.backgroundColor = Colors.white()
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.setUpHeaderView()
self.createTableView()
self.getData()
self.listenToNotifications()
self.automaticallyAdjustsScrollViewInsets = false
if #available(iOS 9.0, *) {
registerForPreviewingWithDelegate(self, sourceView: collectionsTableView!)
}
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden(false, animated: animated)
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
}
func listenToNotifications() {
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(CollectionsViewController.cityChanged), name: Constants.NOTIFIICATION_LOCATION_CHANGED_CITY, object: nil)
}
func cityChanged() {
self.getData()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
collectionsTableView?.frame = CGRectMake(0, Constants.NAV_BAR_HEIGHT, self.view.width, self.view.height - Constants.NAV_BAR_HEIGHT)
}
//MARK: view creation functions
func setUpHeaderView() {
self.navigationItem.title = "Collections"
let negativeSpacer = UIBarButtonItem.init(barButtonSystemItem: UIBarButtonSystemItem.FixedSpace, target: nil, action: nil)
negativeSpacer.width = 0;
headerSearchButton = UIBarButtonItem.init(title: "n", style: .Plain, target: self, action: #selector(CollectionsViewController.headerSearchButtonTapped))
headerSearchButton?.width = 40
headerSearchButton?.setTitleTextAttributes([NSFontAttributeName: Fonts.iconFont(18), NSForegroundColorAttributeName: Colors.gray()], forState: .Normal)
self.navigationItem.rightBarButtonItems = [negativeSpacer, headerSearchButton!];
}
func createTableView() {
collectionsTableView = UITableView(frame: CGRectZero, style: .Plain)
collectionsTableView?.separatorStyle = .None
collectionsTableView?.backgroundColor = Colors.white()
collectionsTableView?.dataSource = self
collectionsTableView?.delegate = self
self.view.addSubview(collectionsTableView!)
}
//MARK : tableview delegate methods
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1;
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return collectionArrayApiObject.collectionsArray.count
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return CollectionsTableViewCell.getHeight()
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.row >= collectionArrayApiObject.collectionsArray.count {
return UITableViewCell(frame: CGRectZero)
}
var tableViewCell:CollectionsTableViewCell? = tableView.dequeueReusableCellWithIdentifier("collectionsCell") as? CollectionsTableViewCell
if (tableViewCell == nil) {
tableViewCell = CollectionsTableViewCell(style: .Default, reuseIdentifier: "collectionsCell")
}
let collectionObject = collectionArrayApiObject.collectionsArray[indexPath.row]
tableViewCell!.setCollection(collectionObject)
return tableViewCell!
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
Commons.trackEvent(Commons.createGAcategory([Constants.COLLECTIONS_PAGE, "collection"]), action: "click", label: nil, value: 1)
let exploreFeedForCollection = ExploreFeedViewController.init(collection: collectionArrayApiObject.collectionsArray[indexPath.row])
//self.presentViewController(CUINavigationController.init(rootViewController: exploreFeedForCollection), animated: true, completion: nil)
self.navigationController?.pushViewController(exploreFeedForCollection, animated: true)
}
func scrollViewDidScroll(scrollView: UIScrollView) {
let contentOffset = scrollView.contentOffset.y
if (collectionsTableView != nil) {
for cell in collectionsTableView!.visibleCells {
if (cell.isKindOfClass(CollectionsTableViewCell.self)) {
let cellOffset = cell.y - contentOffset;
//image parallax
let parallaxCut: CGFloat = 0.5
let percent = (cellOffset + cell.height)/(collectionsTableView!.height + cell.height);
let extraHeight = cell.height * (CollectionsTableViewCell.parallaxRatio-1.0) * parallaxCut;
let collectionCell = cell as! CollectionsTableViewCell;
collectionCell.bgImageView.y = -extraHeight*percent;
}
}
}
}
//MARK : get cities data functions
func getData() {
collectionArrayApiObject = CollectionArrayApiObject()
collectionArrayApiObject.fetchCollections(Delegate: self, CityId: self.cityId)
if collectionArrayApiObject.collectionsArray.count == 0 {
self.showLoader("Hmm, things are getting interesting")
}
}
func collectionsFetchedSuccessfully() {
self.hideNothingHereViewAndLoader()
self.collectionsTableView?.reloadData()
self.scrollViewDidScroll(self.collectionsTableView!)
}
func collectionsFetchingFailed(errorType: ErrorType) {
self.showNothingHereView(errorType, icon: nil, showTryAgain: true)
}
override func didTapReloadButton() {
self.getData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK: UIViewControllerPreviewingDelegate
func previewingContext(previewingContext: UIViewControllerPreviewing, viewControllerForLocation location: CGPoint) -> UIViewController? {
guard let indexPath = collectionsTableView?.indexPathForRowAtPoint(location) else{
return nil
}
// Lifting cell up on 3D touch before peeking
if #available(iOS 9.0, *) {
let cellRect = collectionsTableView?.rectForRowAtIndexPath(indexPath)
let sourceRect = previewingContext.sourceView.convertRect(cellRect!, fromView: collectionsTableView)
previewingContext.sourceRect = sourceRect
}
return ExploreFeedViewController.init(collection: collectionArrayApiObject.collectionsArray[(indexPath as NSIndexPath).row])
}
func previewingContext(previewingContext: UIViewControllerPreviewing, commitViewController viewControllerToCommit: UIViewController) {
self.navigationController?.pushViewController(viewControllerToCommit, animated: true)
}
//MARK : header button functions
func headerSearchButtonTapped() {
let searchVC = SearchViewController(CityId: cityId)
self.navigationController?.pushViewController(searchVC, animated: true)
}
deinit {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
}
Some observations:
First
Instead of using this if statement:
if indexPath.row >= collectionArrayApiObject.collectionsArray.count {
return UITableViewCell(frame: CGRectZero)
}
You should use the numberOfRowsInSection to do that, like this:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return collectionArrayApiObject.collectionsArray.count
}
Second
In your cellForRowAtindexPath you just have to dequeue the cell and than set it as you need, like this:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//swift 3.0
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CollectionsTableViewCell
//swift 2.2
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! CollectionsTableViewCell
let collectionObject = collectionArrayApiObject.collectionsArray[indexPath.row]
cell.setCollection(collectionObject)
return cell
}
There isn't need to test if you use dequeueReusableCellWithIdentifier:forIndexPath:) which according to the docs always returns a valid cell
1- if you are using like this
let cell = tableChatHome.dequeueReusableCell(withIdentifier: "tableChatHomeCell1", for: indexPath) as! tableChatHomeCell1
2- change to like this work fine for me
let cell = tableView.dequeueReusableCell(withIdentifier: "tableChatHomeCell1") as! tableChatHomeCell1

Swift/iOS: Collapsing a section in a UITableView

I have a UITableView with about 5 sections. I am trying to collapse and expand one of those section by the click of a button, but I am seeing an issue where the code I'm using to do so results in the collapsing of other sections as well. Specifically, the first row of all visible sections are collapsed.
Here is what that code looks like:
func didClickSectionCollapseButton() {
shouldCollapseSection = !shouldCollapseSection
tableView.beginUpdates()
tableView.reloadSections(NSIndexSet(index: 1), withRowAnimation: .Fade)
tableView.endUpdates()
}
And here is the numberOfRowInSection method:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section {
case 0:
return 1
case 1:
// collapsible section
return shouldCollapse ? 0 : collapsibleSectionCellCount
case 2:
return getCellCount()
case 3:
return 1
case 4:
return 1
default:
return 0
}
}
Is there anything I'm missing here? I've gone through various tutorials and questions, but I haven't been able to find a solution yet.
Hi after a lot of research, i found a solution which worked for me perfectly using storyboard.
View controller code:
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tblView: UITableView!
var sections = ["section1","section2","section3"]
var cells = ["cell1","cell2","cell3","cell4"]
var selectedIndx = -1
var thereIsCellTapped = false
override func viewDidLoad() {
super.viewDidLoad()
tblView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSections(in tableView: UITableView) -> Int {
return sections.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section {
case 0:
return 2
case 1:
return 3
default:
return 4
}
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.section == selectedIndx && thereIsCellTapped{
return 50
}else{
return 0
}
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerCell = tableView.dequeueReusableCell(withIdentifier: "SectionTableViewCell") as! SectionTableViewCell
headerCell.lblHeader.text = sections[section]
headerCell.btnSelection.tag = section
headerCell.btnSelection.addTarget(self, action: #selector(ViewController.btnSectionClick(sender:)), for: .touchUpInside)
return headerCell
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ExpandeTableViewCell") as! ExpandeTableViewCell
cell.lblCell.text = cells[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print(indexPath.section)
}
#objc func btnSectionClick(sender:UIButton!){
print("selected index",sender.tag)
if selectedIndx != sender.tag {
self.thereIsCellTapped = true
self.selectedIndx = sender.tag
}
else {
// there is no cell selected anymore
self.thereIsCellTapped = false
self.selectedIndx = -1
}
tblView.reloadData()
}
}
If you don't want to do select and unselect on the same selection then, see code below.
#objc func btnSectionClick(sender:UIButton!){
print("selected index",sender.tag)
selectedIndx = sender.tag
tblView.reloadData()
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.section == selectedIndx{
return 50
}else{
return 0
}
}
It works for me, i referred lot of answers and made it. I hope it will help you.
I've Used this code long time ago it is in Swift 2.3. I don't know if this will help or not but worth to mention it.
class DriversVC : UIViewController , UITableViewDelegate , UITableViewDataSource {
//-----------------------------------------------------------------------
//MARK: - Outlets
#IBOutlet var tvDriverList: UITableView! {
didSet {
tvDriverList.delegate = self
tvDriverList.dataSource = self
}
}
//-----------------------------------------------------------------------
//MARK: - Variables
var arrDriverList : NSArray? //Section data
var arrWorkerList : NSArray? //Section data
var collapseSection0 : Bool = false
var collapseSection1 : Bool = false
var btnSection0Headder : UIButton = UIButton()
var btnSection1Headder : UIButton = UIButton()
//------------------------------------------------------
func btnSection0HeadderTapped () {
if collapseSection0 {
collapseSection0 = false
} else {
collapseSection0 = true
}
tvDriverList.reloadSections(NSIndexSet(index: 0), withRowAnimation: UITableViewRowAnimation.Fade)
}
//------------------------------------------------------
func btnSection1HeadderTapped () {
if collapseSection1 {
collapseSection1 = false
} else {
collapseSection1 = true
}
tvDriverList.reloadSections(NSIndexSet(index: 1), withRowAnimation: UITableViewRowAnimation.Fade)
}
//-----------------------------------------------------------------------------------
//MARK:- Table delegate and data sources
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50
}
//------------------------------------------------------
func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 20
}
//------------------------------------------------------
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.mainScreen().bounds.width, height: 50))
view.backgroundColor = OrangeColor //Set your color
let lbl = UILabel(frame: CGRect(x: 10, y: 5, width: UIScreen.mainScreen().bounds.width - 20, height: 40))
lbl.font = UIFont(name: OpenSansRegular, size: 18) //Set your font
lbl.textColor = UIColor.whiteColor()
view.addSubview(lbl)
if section == 0 {
lbl.text = "D R I V E R"
btnSection0Headder.addTarget(self, action: #selector(self.btnSection0HeadderTapped), forControlEvents: .TouchUpInside)
btnSection0Headder.frame = view.frame
view.addSubview(btnSection0Headder) // uncomment to apply collapse effect
} else {
lbl.text = "W O R K E R"
btnSection1Headder.addTarget(self, action: #selector(self.btnSection1HeadderTapped), forControlEvents: .TouchUpInside)
btnSection1Headder.frame = view.frame
view.addSubview(btnSection1Headder) // uncomment to apply collapse effect
}
return view
}
//------------------------------------------------------
func tableView(tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
return UIView()
}
//------------------------------------------------------
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
if arrWorkerList != nil && arrWorkerList?.count > 0 {
return 2
}
return 1
}
//------------------------------------------------------
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
if !collapseSection0 {
guard arrDriverList != nil else {return 0}
return arrDriverList!.count
} else {
return 0
}
} else {
if !collapseSection1 {
guard arrWorkerList != nil else {return 0}
return arrWorkerList!.count
} else {
return 0
}
}
}
//------------------------------------------------------
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCellWithIdentifier(NSStringFromClass(DriversCVC).componentsSeparatedByString(".").last!) as? DriversCVC else { fatalError("unexpected DriversCVC dequeued from tableView") }
cell.superViewController = self
if indexPath.section == 0 {
guard let dict = arrDriverList![indexPath.row] as? NSDictionary else {return cell}
cell.data = dict
} else {
guard let dict = arrWorkerList![indexPath.row] as? NSDictionary else {return cell}
cell.data = dict
}
cell.setup()
return cell
}
//----------------------------------------------------------------------
//MARK: - Action Method
#IBAction func btnBackTapped(sender: AnyObject) {
guard self.navigationController != nil else {
self.dismissViewControllerAnimated(true, completion: nil)
return
}
guard self.navigationController?.popViewControllerAnimated(true) != nil else {
guard self.navigationController?.dismissViewControllerAnimated(true, completion: nil) != nil else {
AppDelegate.sharedInstance().loginCall()
return
}
return
}
}
//-----------------------------------------------------------------------
//MARK: - View Life Cycle Methods
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
//----------------------------------------------------------------------
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
setUpVC()
}
//----------------------------------------------------------------------
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
} }
You can use:
func didClickSectionCollapseButton() {
shouldCollapseSection = !shouldCollapseSection
tableView.beginUpdates()
tableView.deleteSections(NSIndexSet(index: 1), withRowAnimation: .Fade)
tableView.endUpdates()
}
beginUpdates() and endUpdates() works in pair if you want subsequent insertions, deletion, and selection operations, but not for the reloadData.
In your code, remove beginUpdates() and endUpdates().
Is there a difference between the shouldCollapseSection variable being set in the button action and the shouldCollapse variable used in the numberOfRowsInSection method ?
It would seem that you are not setting the same variable you are using in the data source delegate.

Issue in using Tabbarcontroller

i am using TabbarController with four tabbarItem. but my requirement is Tabbar is shown in Top on viewController so that is done.but issue is when adding dropdownview on viewcontroller Tabbar hides dropdown. please help me
My viewController Class Code
import UIKit
class TrendingVC: UIViewController,DropDownViewDelegate
{
#IBOutlet var btndropdown: UIButton!
var dropdown = DropDownView()
override func viewDidLoad() {
super.viewDidLoad()
dropdown = dropdown.initWithArrayData(["1111111111","222222222","3233333333","33333333333","1222333333"], cHeight: 30, tableviewHight: 150, tPaddingTop:0, tPaddingLeft: 0, tPaddingRight: 0, refView: btndropdown, tAnimation:AnimationType.GROW, openAnimationDuration: 0.5, closeAnimationDuration: 0.5, Dropdowncolor: UIColor.purpleColor(), DropdowntextColor: UIColor.whiteColor(), DropdowntextSize: 17) as! DropDownView
dropdown.delegate = self;
self.view.addSubview(dropdown.view);
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func DropDownCellSelected(index: NSInteger)
{
print(index);
}
#IBAction func btndropdownclik(sender:UIButton!)
{
self.view.bringSubviewToFront(dropdown.view)
dropdown.OpenAnimation()
}
My Custom Dropdown Class Code Here
import UIKit
enum AnimationType
{
case BLENDIN
case GROW
case BOTH
}
protocol DropDownViewDelegate
{
func DropDownCellSelected(index:NSInteger) -> Void
}
class DropDownView: UIViewController,UITableViewDelegate,UITableViewDataSource
{
var arrDropDown = NSMutableArray()
var delegate: DropDownViewDelegate!
var OPENAnimationDuration,CLOSEAnimationDuration,DropdownViewTextsize,CellHight,DropDownHight,LeftMargin,RightMargin,TopMargin:CGFloat!
var refillview:UIView!
var DropdownViewColor,DropDownviewTextcolor:UIColor!
var animationType:AnimationType!
var tbl:UITableView!
override func viewDidLoad()
{
super.viewDidLoad()
let refFrame:CGRect = refillview.frame;
tbl = UITableView();
tbl.frame = CGRectMake(0, 0, refFrame.size.width+RightMargin, (animationType == AnimationType.BOTH||animationType == AnimationType.BLENDIN) ?DropDownHight:1)
tbl.dataSource = self;
tbl.delegate = self;
//uiTableView.backgroundColor=[UIColor colorWithRed:15/255 green:41/255 blue:63/255 alpha:1];
tbl.backgroundColor = UIColor.clearColor()
self.view.addSubview(tbl)
self.view.hidden = true;
if (animationType == AnimationType.BOTH || animationType == AnimationType.BOTH)
{
self.view.alpha = 1;
}
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Tableview Methods
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrDropDown.count;
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1;
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cellidentifier:NSString = "CellId";
var cell:UITableViewCell? = tableView.dequeueReusableCellWithIdentifier(cellidentifier as String)
if cell==nil
{
cell = UITableViewCell.init(style: UITableViewCellStyle.Default, reuseIdentifier: cellidentifier as String)
}
cell!.backgroundColor = UIColor.purpleColor();
cell!.textLabel?.text = arrDropDown.objectAtIndex(indexPath.row) as? String
cell!.selectionStyle = UITableViewCellSelectionStyle.None;
cell!.textLabel?.font = UIFont(name:"helvetica" , size: 20)
return cell!
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
{
return CellHight;
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
self.CloseAnimation()
delegate.DropDownCellSelected(indexPath.row)
}
func OpenAnimation()
{
self.view.hidden = false
//var newCenter:CGPoint = CGPointMake(playAgainButton.center.x, playAgainButton.center.y + 200)
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(1.0)
tbl.frame = CGRectMake(tbl.frame.origin.x,tbl.frame.origin.y,tbl.frame.size.width, DropDownHight);
UIView.commitAnimations()
}
func CloseAnimation()
{
self.view.hidden = false;
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(1.0)
tbl.frame = CGRectMake(tbl.frame.origin.x,tbl.frame.origin.y,tbl.frame.size.width, 0);
UIView.commitAnimations()
}
func OpenAnimationWithRef()
{
}
func initWithArrayData(data:NSArray,cHeight:CGFloat,tableviewHight:CGFloat,tPaddingTop:CGFloat,tPaddingLeft:CGFloat,tPaddingRight:CGFloat,refView:UIView!,tAnimation:AnimationType,openAnimationDuration:CGFloat,closeAnimationDuration:CGFloat,Dropdowncolor:UIColor!,DropdowntextColor:UIColor!,DropdowntextSize:CGFloat) -> AnyObject
{
arrDropDown=data.mutableCopy() as! NSMutableArray;
CellHight = cHeight;
DropDownHight = tableviewHight;
TopMargin = tPaddingTop;
LeftMargin = tPaddingLeft;
RightMargin = tPaddingRight;
refillview = refView;
OPENAnimationDuration = openAnimationDuration;
CLOSEAnimationDuration = closeAnimationDuration;
animationType = tAnimation;
DropdownViewColor = Dropdowncolor;
DropDownviewTextcolor = DropdowntextColor;
DropdownViewTextsize = DropdowntextSize;
let reframe = refView.frame;
self.view.frame = CGRectMake(reframe.origin.x-LeftMargin, reframe.origin.y+reframe.size.height+TopMargin, reframe.size.width+RightMargin,DropDownHight);
self.view.layer.shadowColor = UIColor.clearColor().CGColor
self.view.layer.shadowOffset = CGSizeMake(5.0, 5.0)
self.view.layer.shadowOpacity = 1.0;
self.view.layer.shadowRadius = 5.0;
tbl.layer.cornerRadius = 5.0;
tbl.layer.borderWidth = 3.0;
tbl.layer.borderColor = UIColor.darkGrayColor().CGColor;
tbl.autoresizingMask = UIViewAutoresizing.FlexibleWidth;
return self
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}

TableView resizing - only when button clicks

I am having some issues with my table view resizing - As it looks when the page loads :
And then once the button is clicked
As you can see, the button click renders the table to be of the correct size - how can I achieve this from the outset - as it makes it look much neater
My code for the class is as follows;
//
// FirstViewController.swift
// Intercultural Collaboration
//
// Created by Ricki Lambert on 06/10/2014.
// Copyright (c) 2014 com.kentapps. All rights reserved.
//
import UIKit
class QuizViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UIAlertViewDelegate{
var countries:Array<Answer> = [];
var selected = -1;
var positionOfSelected = 1;
#IBOutlet var next: UIBarButtonItem!
#IBOutlet var tableView: UITableView!
#IBAction func next(sender: AnyObject) {
}
func checkOkToProceed() -> Bool {
positionOfSelected = 1;
var result = false;
for answer in countries{
if(answer.selected){
result = true;
break;
}
positionOfSelected++;
}
return result;
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if(sender.tag > 0 && !self.checkOkToProceed()){
//the user has not selected an answer so
//we need to show them a prompt
var alert = UIAlertController(title: "Unanswered Question", message: "Please select an answer!", preferredStyle: UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(title: "Ok", style: UIAlertActionStyle.Default, handler: nil))
self.presentViewController(alert, animated: true, completion: nil);
}
}
override func viewDidLoad() {
super.viewDidLoad();
tableView.reloadData();
//load answers to countries array
self.tableView.allowsMultipleSelection = false;
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1;
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.countries.count;
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("CountryCell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel?.text = self.countries[indexPath.row].answerName;
cell.textLabel?.textAlignment = NSTextAlignment.Center;
let countryImage = String(self.countries[indexPath.row].answerName) + ".png";
cell.imageView?.image = UIImage(named: countryImage);
if(countries[indexPath.row].selected){
let imageName = "tick.png";
let image: UIImageView = UIImageView(image: UIImage(named: imageName));
cell.accessoryView = image;
}else{
let image: UIImageView = UIImageView();
cell.accessoryView = image;
}
tableView.sizeToFit();
return cell;
}
func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
countries[indexPath.row].setSelected(true);
if(selected != -1){
countries[selected].setSelected(false);
}
selected = indexPath.row;
tableView.reloadData();
}
func alertView(alertView: UIAlertView!, clickedButtonAtIndex buttonIndex: Int) {
if (buttonIndex == 0) {
//Do something
}
}
}
I recently had this issue. Here is an elegant solution:
tableView.tableFooterView = UIView()

Resources