Problems :
UITableview populate duplicate data even after removing the array when it dismiss
Expected output:
UITableview populate data based on itenary items in array
Actual output:
UITableView populates the correct amount output when the user selects the first location in DiscoverVC but when the user selects another location, the tableview append the itenary data that the user-selected previouly.
Summary:
I have 3VC in my project, first vc (DiscoverVC), will call api to populate data in UICollectionView, I implement UICollectionView Delegate to move to another screen with segue, in prepare segue I pass data from the first vc to second vc (ItenaryVC), in second vc i have 2 view inside it. One normal vc and the second is floating panel (ItenaryFP). When second vc loads up it will make API calls base on Location object that had been pass from first vc and pass the data to the third vc which is floating panel (ItenaryFP) through delegate in ItenaryVC.
PS; I use custom cell for the tableview and have, I also already try to remove the array from viewWillAppear and viewDidDissapear but it's still not working
GIF of how the issues occurs
Here is a summary of my code
DiscoverVC.swift
class DiscoverVC : UIViewController {
//MARK:- IBOutlets
#IBOutlet weak var collectionView: UICollectionView!
private var locationResult = [Location]()
private var selectedAtRow : Int!
//MARK:- Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
renderView()
getLocations()
}
private func renderView() {
collectionView.register(UINib(nibName: R.nib.discoverCell.name, bundle: nil), forCellWithReuseIdentifier: R.reuseIdentifier.discoverCell.identifier)
collectionView.delegate = self
collectionView.dataSource = self
}
private func getLocations(location : String = "locations") {
NetworkManager.shared.getLocations(for: location) { [weak self] location in
switch location {
case .success(let locations):
self?.updateDiscoverUI(with: locations)
case .failure(let error):
print(error.rawValue)
}
}
}
private func updateDiscoverUI(with locations : [Location]) {
DispatchQueue.main.async { [weak self] in
self?.locationResult.append(contentsOf: locations)
self?.collectionView.reloadData()
}
}
}
//MARK:- Delegate
extension DiscoverVC : UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectedAtRow = indexPath.row
self.performSegue(withIdentifier: R.segue.discoverVC.goToDetails, sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let destinationVC = segue.destination as? ItenaryVC else { return}
// Passing location object to ItenaryVC
destinationVC.locationName = locationResult[selectedAtRow]
destinationVC.imageURL = locationResult[selectedAtRow].image
// Remove tab bar when push to other vc
destinationVC.hidesBottomBarWhenPushed = true
}
}
ItenaryVC.swift
protocol ItenaryVCDelegate : AnyObject {
func didSendItenaryData(_ itenaryVC : ItenaryVC, with itenary : [[Days]])
func didSendLocationData(_ itenaryVC : ItenaryVC, with location : Location)
}
class ItenaryVC: UIViewController {
#IBOutlet weak var backgroundImage: UIImageView!
var fpc : FloatingPanelController!
var imageURL : URL?
var locationName: Location?
weak var delegate : ItenaryVCDelegate?
//MARK:- Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
setupCard()
setupView()
}
override func viewWillAppear(_ animated: Bool) {
// Call API for data
getItenaries(at: locationName!.itenaryName)
print("ItenaryVC Appear")
}
override func viewWillDisappear(_ animated: Bool) {
locationName = nil
}
}
//MARK:- Network Request
extension ItenaryVC {
func getItenaries(at itenaries : String = "Melaka"){
print("itenaries : \(itenaries)")
NetworkManager.shared.getItenaries(for: itenaries) { [weak self] itenary in
switch itenary {
case .success(let itenary):
// print(itenary)
DispatchQueue.main.async {
// Passing data to itenaryFP
self?.delegate?.didSendItenaryData(self! , with: itenary)
}
print(itenaries.count)
case .failure(let error):
print(error.rawValue)
}
}
}
}
//MARK:- Private methods
extension ItenaryVC {
private func setupView() {
backgroundImage.downloaded(from: imageURL!)
backgroundImage.contentMode = .scaleAspectFill
// Passing data to itenaryFP
delegate?.didSendLocationData(self, with: locationName!)
}
private func setupCard() {
guard let itenaryFlotingPanelVC = storyboard?.instantiateViewController(identifier: "itenaryPanel") as? ItenaryFP else { return}
// Initliase delegate to Floating Panel, create strong reference to Panel
self.delegate = itenaryFlotingPanelVC
fpc = FloatingPanelController()
fpc.set(contentViewController: itenaryFlotingPanelVC)
fpc.addPanel(toParent: self)
fpc.delegate = self
fpc.layout = self
}
}
ItenaryFP.swift
class ItenaryFP: UIViewController{
var itenaries = [[Days]]()
var location : Location?
//MARK:- : Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
print("ItrenaryFP viewDidLoad, itenaries : \(itenaries.count), location : \(location)")
renderView()
}
override func viewWillAppear(_ animated: Bool) {
itenaries.removeAll()
itenaryTableView.reloadData()
}
override func viewWillDisappear(_ animated: Bool) {
DispatchQueue.main.async {
self.itenaries.removeAll()
print("ItenarFP dissapear, itenaries :\(self.itenaries.count), location : \(self.location)")
self.location = nil
self.itenaryTableView.reloadData()
}
}
private func renderView() {
itenaryTableView.register(UINib(nibName: R.nib.itenaryCell.name, bundle: nil), forCellReuseIdentifier: R.nib.itenaryCell.identifier)
itenaryTableView.dataSource = self
itenaryTableView.delegate = self
locDescHC.constant = locDesc.contentSize.height
}
}
//MARK:- Data source
extension ItenaryFP : UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return itenaries.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return itenaries[section].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell : ItenaryCell = itenaryTableView.dequeueReusableCell(withIdentifier: R.nib.itenaryCell.identifier, for: indexPath) as! ItenaryCell
let listOfItenaries = itenaries[indexPath.section][indexPath.row]
cell.cellContent(for: listOfItenaries)
return cell
}
}
//MARK:- ItenaryVC Delegate
extension ItenaryFP : ItenaryVCDelegate {
func didSendLocationData(_ itenaryVC: ItenaryVC, with location: Location) {
DispatchQueue.main.async {
self.locationLabel.text = location.locationName
self.locDesc.text = location.description
self.sloganLabel.text = location.slogan
}
}
func didSendItenaryData(_ itenaryVC: ItenaryVC, with itenary: [[Days]]) {
DispatchQueue.main.async {
self.itenaries.append(contentsOf: itenary)
self.itenaryTableView.reloadData()
print("itenary \(self.itenaries.count)")
}
}
}
Use:
self.itenaries = itenary
Instead of:
self.itenaries.append(contentsOf: itenary)
Related
My project is created programmatically without using storyboard. And it is like Apple Music's miniPlayer, when clicking a row in tableView, will update the data of miniPlayer(which is in containerView).
I see some examples with storyboard and segue like below code: call child viewController's method in parent viewController to update data by using protocol & delegate.
But I don't use storyboard, so what is the alternative code to prepare()?
protocol ContentDelegate {
func updateContent(id: Int)
}
class ParentViewController: UIViewController {
var delegate: ContentDelegate?
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "containerController") {
let containerVC = segue.destination as! ChildContainerViewController
self.delegate = containerVC
}
}
}
class ChildContainerViewController: UIViewController, ContentDelegate {
func updateContent(id: Int) {
// your code
}
}
My Code: add container view in the root view controller(UITabViewController).
class ViewController: UITabBarController {
// mini player
var miniPlayer: MiniPlayerViewController?
// container view
var containerView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
// set tabBar and other stuff
...
configureContainer()
}
func configureContainer() {
// add container
containerView = UIView()
containerView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(containerView)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
containerView.leadingAnchor.constraint(equalTo: g.leadingAnchor),
containerView.trailingAnchor.constraint(equalTo: g.trailingAnchor),
containerView.bottomAnchor.constraint(equalTo: tabBar.topAnchor),
containerView.heightAnchor.constraint(equalToConstant: 64.0)
])
// add child view controller view to container
miniPlayer = MiniPlayerViewController()
guard let miniPlayer = miniPlayer else { return }
addChild(miniPlayer)
miniPlayer.view.translatesAutoresizingMaskIntoConstraints = false
containerView.addSubview(miniPlayer.view)
// Create and activate the constraints for the child’s view.
guard let miniPlayerView = miniPlayer.view else { return }
NSLayoutConstraint.activate([
miniPlayerView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor),
miniPlayerView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor),
miniPlayerView.topAnchor.constraint(equalTo: containerView.topAnchor),
miniPlayerView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor),
])
miniPlayer.didMove(toParent: self)
}
}
I want to trigger the update when clicking the row in parentView.
protocol ContentDelegate {
func configure(songs: [Song]?, at index: Int)
}
class SongsListViewController: UIViewController {
private var tableView: UITableView!
var delegate: ContentDelegate?
// MARK: - data source
var songs = [Song]()
. . .
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let index = indexPath.row
let vc = MiniPlayerViewController()
self.delegate = vc
self.delegate?.configure(songs: songs, at: index)
// present(vc, animated: true)
}
The update method in child view.
extension MiniPlayerViewController {
func configure(songs: [Song]?, at index: Int) {
if let songs = songs {
let song = songs[index]
songTitle.text = song.title
thumbImage.image = song.artwork?.image
} else {
// placeholder fake info
songTitle.text = "你在终点等我"
thumbImage.image = UIImage(named: "Wang Fei")
}
}
}
There is more than one approach to this...
First approach - no custom delegate:
Use the subclassed UITabBarController as an "intermediary". Give it a func such as:
func configure(songs: [Song]?, at index: Int) -> Void {
miniPlayer.configure(songs: songs, at: index)
}
then, in your "Select Song" view controller (one of the tabs):
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard let tbc = self.tabBarController as? CustomTabBarController else {
return
}
let index = indexPath.row
tbc.configure(songs: songs, at: index)
}
Second approach - using a custom delegate:
protocol ContentDelegate {
func configure(songs: [Song]?, at index: Int)
}
Make sure your "mini player" controller conforms to the delegate:
class MiniPlayerViewController: UIViewController, ContentDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// add UI elements, any other setup code
}
}
extension MiniPlayerViewController {
func configure(songs: [Song]?, at index: Int) {
if let songs = songs {
let song = songs[index % songs.count]
songTitle.text = song.title
thumbImage.image = song.artwork
} else {
// placeholder fake info
songTitle.text = "你在终点等我"
thumbImage.image = UIImage(named: "Wang Fei")
}
}
}
Give your "Select Song" view controller (and any other of the tab controllers) a delegate var:
class SelectSongViewController: UIViewController {
var delegate: ContentDelegate?
// everything else
}
then, in your subclassed UITabBarController:
override func viewDidLoad() {
super.viewDidLoad()
configureContainer()
if let vc = viewControllers?.first as? SelectSongViewController {
vc.delegate = miniPlayer
}
}
now your "Select Song" view controller can call the delegate func:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard let tbc = self.tabBarController as? CustomTabBarController else {
return
}
let index = indexPath.row
delegate?.configure(songs: songs, at: index)
}
I am confused to why my table view is not reloading after i call the tableView.reloadData() function. Here is what you should know about my project. The initial view controller is a tableViewController and when you click the add button in the navigation bar it pulls up presents the "addItemViewController". It is presented overCurrentContext. Everything to this point works fine, but the part that doesn't work is when you fill out the info in the pop up I created and push the button to save it it saves to the core data fill but when i reload it it doesnt even call that. When i close the app and reload it the data shows up but it doesnt show up when i add it and call the same function.
import UIKit
import CoreData
protocol reloadTableView: class {
func reloadTableView()
}
class TableViewController: UITableViewController {
//Global Variables
let addItemVC = AddItemController()
var itemArray = [Item]()
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
override func viewDidLoad() {
super.viewDidLoad()
addItemVC.delegate = self
loadItems()
}
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return itemArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: Constants.cellIdentifier, for: indexPath) as! Cell
let array = itemArray[indexPath.row]
cell.dateCreated.text = array.dateCreated
cell.workoutLabel.text = array.workoutName
cell.weightLifted.text = array.weight
return cell
}
//MARK: - Add Button Pressed
#IBAction func addItemPressed(_ sender: UIBarButtonItem) {
let storyboard = UIStoryboard(name: "AddItem", bundle: nil)
let addItemVC = storyboard.instantiateViewController(identifier: "AddItemController")
addItemVC.isModalInPresentation = true
addItemVC.modalPresentationStyle = .overCurrentContext
addItemVC.modalTransitionStyle = .crossDissolve
addItemVC.navigationController?.isNavigationBarHidden = true
present(addItemVC, animated: true, completion: nil)
}
//MARK: - Create and Load Functions
func saveData() {
do {
try context.save()
} catch {
print("Error Saving Data \(error)")
}
tableView.reloadData()
}
func loadItems() {
let request: NSFetchRequest<Item> = Item.fetchRequest()
do {
itemArray = try context.fetch(request)
} catch {
print("error")
}
tableView.reloadData()
}
}
//MARK:// - Add Item Vc Delegate
extension TableViewController: reloadTableView {
func reloadTableView() {
do {
try context.save()
} catch {
print("Error Saving Data \(error)")
}
let request: NSFetchRequest<Item> = Item.fetchRequest()
do {
itemArray = try context.fetch(request)
} catch {
print("error")
}
tableView.reloadData()
print("There are", itemArray.count, "in the item array")
print(itemArray.last?.workoutName)
//the print statement are not showing up in console
}
}
and the second file
import UIKit
import CoreData
class AddItemController: UIViewController {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var delegate: reloadTableView?
#IBOutlet weak var viewContainer: UIView!
#IBOutlet weak var exercise: UITextField!
#IBOutlet weak var weight: UITextField!
#IBOutlet weak var reps: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func addMaxPressed(_ sender: UIButton) {
if exercise.text != "" && weight.text != "" && reps.text != "" {
let newItem = Item(context: context)
let formatter = DateFormatter()
newItem.dateCreated = formatter.formattedDate()
newItem.weight = weight.text
newItem.reps = reps.text
newItem.workoutName = exercise.text
dismiss(animated: true) {
self.delegate?.reloadTableView()
}
}
}
#IBAction func exitPressed(_ sender: UIButton) {
dismiss(animated: true, completion: nil)
}
}
//MARK: - UITextField func
extension AddItemController: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
self.view.endEditing(true)
return true
}
}
You're setting the delegate on the wrong instance of the add item view controller.
You create one instance with...
let addItemVC = AddItemController()
...and another with...
let addItemVC = storyboard.instantiateViewController(identifier: "AddItemController")
You set the delegate on the first of those, but present the second. That means when you get to...
self.delegate?.reloadTableView()
...of the presented controller, nothing happens.
If you're not using the first instance, get rid of it and set the delegate in the same section where you set the presentation style, etc.
When you put ? after an optional, it means you don't want to know whether it did what you asked or not. Obviously, you do want to know so you should test the value instead and print a message if the value isn't what you expect.
I am trying to create new category in 1 view controller (AddCategoryViewController) and show it in table view controller (CategoryViewController). But there's an issue with reloading data.
New category item shows only after turning on and off the app, even when there is tableView.reloadData().
I tried to change the title of navigation in addButtonPressed function and the title changes immediately.
When I was using UIAlertView to add data, tableView.reloadData() worked. So I guess it's something with 2 view controllers and delegate methods?
Thanks for your help <3
show item:
import UIKit
import CoreData
class CategoryViewController: UITableViewController {
#IBOutlet weak var navigation: UINavigationItem!
var categoryArray = [Category]()
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
override func viewDidLoad() {
super.viewDidLoad()
loadCategory()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return categoryArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .default, reuseIdentifier: "CategoryItemCell")
cell.textLabel?.text = categoryArray[indexPath.row].name
if let randomColor = categoryArray[indexPath.row].color {
cell.textLabel?.textColor = UIColor(hex: randomColor)
}
return cell
}
// MARK: - Table view data source
#IBAction func addPressed(_ sender: UIBarButtonItem) {
let addCategoryVC = storyboard?.instantiateViewController(withIdentifier: "AddCategoryViewController") as! AddCategoryViewController
addCategoryVC.delegate = self
present(addCategoryVC, animated: true, completion: nil)
}
// MARK: - CoreData methods
func saveCategory() {
do {
try context.save()
} catch {
print("Save error: \(error)")
}
tableView.reloadData()
}
func loadCategory(with request: NSFetchRequest<Category> = Category.fetchRequest()) {
do {
categoryArray = try context.fetch(request)
} catch {
print("Load error: \(error)")
}
tableView.reloadData()
}
func addCategory(name: String, description: String) {
let newCategory = Category(context: context.self)
newCategory.name = name
newCategory.descriptionOfCategory = description
newCategory.color = UIColor.random().toHex
saveCategory()
print("name form func: \(name)")
print("description from func: \(description)")
}
}
// MARK: AddCateogry delegate methods
extension CategoryViewController: AddCategoryDelegate {
func addButtonPressed(name: String, description: String) {
addCategory(name: name, description: description)
navigation.title = "I have changed!"
}
}
Add item:
import UIKit
protocol AddCategoryDelegate {
func addButtonPressed(name: String, description: String)
}
class AddCategoryViewController: UIViewController {
var delegate : AddCategoryDelegate!
#IBOutlet weak var nameTextField: UITextField!
#IBOutlet weak var descriptionTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func addCategoryButtonPressed(_ sender: UIButton) {
delegate.addButtonPressed(name: nameTextField.text!, description: descriptionTextField.text!)
dismiss(animated: true, completion: nil)
}
}
You only save the category to coredata inside addCategory , but you have to add the item to the array also , or call loadCategory before tableView.reloadData() inside saveCategory
The issue is this:
In the storyboard, I must uncheck the Adjust Scroll View Insets, because if not do this, I will get a other issue(https://stackoverflow.com/questions/40974647/uisearchcontroller-issue-nslayoutattribute-do-not-work-in-real-device), and I don't know this if is affect the issue here.(I test in simulator, if check Adjust Scroll View Insets, the issue here will not appear )
My code
import UIKit
import SVProgressHUD
class ChooseStoreViewController: UIViewController,UISearchBarDelegate, UITableViewDelegate, UITableViewDataSource, UISearchResultsUpdating {
#IBOutlet weak var tableView: UITableView!
var ori_dataSource: [StoreListModel] = [StoreListModel]()
var dataSource = [String]()
var filterdDataSource = [String]()
var resultSearchController = UISearchController()
var choosedStore:StoreListModel? = nil
var userInfoFromChooseTerant:[String:Any]?
#IBOutlet weak var top_constraint: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
initData()
initUI()
}
// MARK: - view life
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.isNavigationBarHidden = false
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.navigationController?.isNavigationBarHidden = true
}
func initData() {
self.resultSearchController = UISearchController(searchResultsController: nil)
self.resultSearchController.searchResultsUpdater = self
self.resultSearchController.dimsBackgroundDuringPresentation = false
self.resultSearchController.searchBar.sizeToFit()
self.resultSearchController.searchBar.placeholder = "search"
self.resultSearchController.searchBar.tintColor = UIColor.black
self.resultSearchController.searchBar.delegate = self
self.tableView.tableHeaderView = self.resultSearchController.searchBar
let nib = UINib(nibName: "TerantListCell", bundle: nil)
// Required if our subclasses are to use: dequeueReusableCellWithIdentifier:forIndexPath:
//tableView.register(nib, forCellReuseIdentifier: "TerantListCell")
self.tableView.register(nib, forCellReuseIdentifier: "TerantListCell")
self.tableView.tableFooterView = UIView.init()
self.tableView.reloadData()
networkForStoreList()
}
func initUI() {
let backNavItem:UIBarButtonItem = UtilSwift.addBackButtonItem(nil, controlelr: self)
backNavItem.action = #selector(navBack)
// print(userInfoFromChooseTerant!)
tableView.separatorStyle = UITableViewCellSeparatorStyle.none
}
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
let chooseRole: ChooseRoleViewController = segue.destination as! ChooseRoleViewController
chooseRole.userInfoFromChooseStore = self.userInfoFromChooseTerant
}
// MARK: - search delegate
func searchBarCancelButtonClicked() {
for item:NSLayoutConstraint in self.tableView.constraints {
self.view.setNeedsLayout()
if item.firstAttribute == NSLayoutAttribute.top {
item.constant = 0
}
}
}
// MARK: - searchbar delegate
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
searchBar.setValue("cancel", forKey:"_cancelButtonText")
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
}
// MARK: - private methods
func navBack() {
_ = self.navigationController?.popViewController(animated: true)
}
// MARK: - actions
#IBAction func unwindToChooseStoreVCFromChooseRole(segue: UIStoryboardSegue){
}
#IBAction func nextStepAction(_ sender: UIButton) {
/*if choosedStore == nil {
let lml_alert: LMLDropdownAlertView = LMLDropdownAlertView.init(frame: self.view.bounds)
lml_alert.showAlert(title: Global.hint, detail_Title: "select", cancleButtonTitle: "cacnel", confirmButtonTitle: "confirm", action: { (button) in
})
return
}*/
self.resultSearchController.isActive = false
if self.choosedStore != nil {
_ = self.userInfoFromChooseTerant?.updateValue(self.choosedStore!.userId, forKey: "store_id")
}
self.performSegue(withIdentifier: "ChooseStoreVCToChooseRoleVC", sender: self)
}
// MARK: - network
func networkForStoreList() {
let params:[String:String] = [
"createTime":"-1",
"userId" : self.userInfoFromChooseTerant!["affiliated_id"] as! String
]
// url_terantList
Mysevers.afpost(withHud: true, andAddressname: Global.url_listStore, parmas: params, requestSuccess: { (result) in
let stateCode = UtilSwift.getNetStateCode(result: result as Any, key: Global.net_key_stateCode)
if stateCode == 0 {
let storeArr:[[String : Any]] = UtilSwift.getNetAnyObject(result: result as Any, key: "list") as! [[String : Any]] // Global.net_key_bussines
//self.ori_dataSource = terantArr
for item:[String: Any] in storeArr {
let store_list_model: StoreListModel = StoreListModel.initStoreListModelWithDic(dic: item)
self.ori_dataSource.append(store_list_model)
}
for item:StoreListModel in self.ori_dataSource {
self.dataSource.append(item.name)
}
self.tableView.reloadData()
}else if stateCode == -1 {
SVProgressHUD.showError(withStatus: "err")
}
}, failBlcok: {
SVProgressHUD.showError(withStatus: "err")
})
}
// MARK: - tableView
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if self.resultSearchController.isActive {
return filterdDataSource.count
}else {
return dataSource.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: TerantListCell = tableView.dequeueReusableCell(withIdentifier: "TerantListCell", for: indexPath) as! TerantListCell
if self.resultSearchController.isActive {
cell.title_label.text = self.filterdDataSource[indexPath.row]
}else {
cell.title_label?.text = self.dataSource[indexPath.row]
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.choosedStore = self.ori_dataSource[indexPath.row]
}
// MARK: - regexp
func updateSearchResults(for searchController: UISearchController) {
self.filterdDataSource.removeAll(keepingCapacity: false)
let searchPredicate = NSPredicate(format: "SELF CONTAINS[c] %#", searchController.searchBar.text!)
let array = (self.dataSource as NSArray).filtered(using: searchPredicate)
self.filterdDataSource = array as! [String]
self.tableView.reloadData()
}
}
Go to ".storyboard" file where "ChooseStoreViewController" exist. Then click on UITableView and change tableView constraints as follows:
Check Top Space constraint.
I would like to make it so that when the user clicks on the cell, it shows exactly everything in the cell. TextView, Buttons, and label. How can I do this?
Here is the code:
TableCell:
import UIKit
class TableViewCell: UITableViewCell {
#IBOutlet weak var textView: UITextView!
#IBAction func 1Button(sender: AnyObject) {
}
#IBAction func 2Button(sender: AnyObject) {
}
#IBOutlet weak var counter: 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
}
}
TableViewController:
import UIKit
let reuseIdentifier = "Cell"
class UserFeedTableViewController: UITableViewController, ComposeViewControllerDelegate {
private var posts: [PFObject]? {
didSet {
tableView.reloadData()
}
}
override func viewDidLoad() {
super.viewDidLoad()
Downloader.sharedDownloader.queryForPosts()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "queryFeeds:", name: queryNotification, object: nil)
}
// Notification SEL
func queryFeeds(notification: NSNotification) {
posts = notification.object as? [PFObject]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "postSegue" {
let nav = segue.destinationViewController as! UINavigationController
let composeVc = nav.topViewController as! ComposeViewController
composeVc.delegate = self
}
if segue.identifier == "commentsSegue" {
let vc = segue.destinationViewController as! CommentsViewController
let cell = sender as! UITableViewCell
let indexPath = tableView.indexPathForCell(cell)
let object = posts![indexPath!.row]
vc.postObject = object
}
}
//dismiss compose vc
func dismissComposeViewController(ViewController: ComposeViewController) {
dismissViewControllerAnimated(true, completion: nil)
}
func reloadTableViewAfterPosting() {
dismissViewControllerAnimated(true, completion: nil)
Downloader.sharedDownloader.queryForPosts()
}
}
extension ViewController {
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return posts?.count ?? 0
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(reuseIdentifier, forIndexPath: indexPath) as! UserFeedTableViewCell
// Configure the cell...
if let posts = posts {
let object = posts[indexPath.row]
cell.textView?.text = object["post"] as? String
}
return cell
}