This app is just for research and learning purposes. I'm new to developing, so there is nothing fancy about that, really.
It should display a TableView with some contacts, which are split into two different categories: Recent & Friends
However, when I try to return those to be displayed as a header (everything else worked just as I intended it to) with the TitleForHeaderInSection function, only one gets displayed eventually. (I used a switch function, so for that matter only case 0 is displaying).
override func numberOfSections(in tableView: UITableView) -> Int {
return 2 // Recent & Friends
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
switch section {
case 0: return "RECENT"
case 1: return "FRIENDS"
default: break
}
return String(section)
}
As seen in the screenshot above, in the app only one of the two cases gets returned and I am genuinely struggling to figure out why.
is it showing sections or sections are missing, not just heading ?if sections are missing then you need to select tableview style grouped in storyboard
Its because you dint implement these delegates :(1) viewforHeaderInSection (2)heightForHeaderInSection
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
//Create label which you want to show on each section header and return it
}
Also use heightForHeaderInsection method .
Hope this help to solve your issue
Related
I have to make a dynamic datasource for a table, that satisfies the criteria:
we do not know exact number of sections
we do not know exact title for header in section
we do not now how many rows it will be in each section each time
To detect number of rows per section I have the following code:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let header = tableView.headerView(forSection: section)
return self.servicesData?.filter({ $0.clubName == header?.textLabel?.text }).count ?? 0
}
where servicesData is the object array that is to be filtered by the header title aka clubName. Titles are gathered from the object array.
For some reason I always get nil when try to access the header. So far I tried calling tableView(_:titleForHeaderInSection:) directly in numberOfRowsInSection but obviously with no luck.
Feedback much appreciated.
It is nil because it is not created at that moment. You should not use tableView.headerView(forSection: section) in numberOfRows. You should use the model from where you get the title to use it to filter in the array.
You should fetch all of your data before populating the table view and first. Then you should implement:
func numberOfSections(in tableView: UITableView) -> Int {
return headerModels.count
}
where headerModels it's an array of objects with your title and it's items like:
class HeaderModel {
let title: String
let items: [YourItem]
}
and then:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return headerModels[section].items.count
}
So, as per #shurtugal 's solution it is possible to pass-in an array of objects to populate the table. I thought that creating a utility class for this very case may be too much. So here's the slightly altered way:
Consider a dictionary var servicesData = [String: [CustomObject]]() that is populated each time the ViewController shows up. The dictionary can have indefinite number of keys and indefinite number of values inside each key. Algorithm of populating the dictionary is taken from this answer.
Thereby, UITableViewDatasource methods can be defined like this:
func numberOfSections(in tableView: UITableView) -> Int {
self.servicesData.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return Array(self.servicesData.values)[section].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
/* cell creation code code */
/// sample line
cell?.someLabel.text = Array(self.servicesData.values)[indexPath.section][indexPath.row]
return cell
}
Using method below of viewForHeaderInSection i try and display an image in table header section one , but i also want a heading text, using the method of heading title text i am able to display the heading for all sections but not section 1 , do i need to make some changes to heading view for section one to be able to display the heading , if i were to remove the viewForHeaderInSection then the title for first header section also shows up
let sectionTitle = ["Feedback", "Follow Us"]
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
if section == 0 {
headerTop.headerLogo.image = UIImage(named: "foodpin-logo")
return headerTop.topView
}
return nil
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return sectionTitle[section]
}
You need to create a text label in your headerTop view and remove this function override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int). So your code will be like this:
let sectionTitle = ["Feedback", "Follow Us"]
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
headerTop.headerLogo.image = (section == 0) ? UIImage(named: "foodpin-logo") : nil
headerTop.yourHeaderTextLabel.text = sectionTitle[section]
return headerTop.topView
}
It seems like you are looking for tableHeaderView! The issue is you are overriding the first section's header.
You may consider setting the tableView's tableHeaderView for the headerTop instead. So all sections will have their titles as you expected.
tableView. tableHeaderView = headerTop
Also, if you want yout table's header to be sticky, there are bunch of tutorials for that.
I need an advice with ViewContoller's scheme. I should create a view with Billing addresses. There can be no address at all, or some addresses. If there no one, there should be only a button "Add New". And if there are addresses, each should have buttons Edit, Remove, and "Add New" too.
I have data for this VC as JSON, parsed and saved to plist.
So what is logic to make this View looks different depends on 1) if there are addresses or not? and 2) if there 1, or 2, or maybe 20 billing addresses?
Thanks a lot!
I solved issues like this with UITableVIew and the UITableViewDataSource and UITableViewDelegate:
setup the table view for one section (adresses)
func numberOfSections(in tableView: UITableView) -> Int {return 1;}
return the address arrays length in the delegate method
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
return adresses.count
}
set the view for footer if the arrays length is 0
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
if adresses.count == 0 {
let vw = YourViewClass()
//I use blockskit library here (vw.bk_) to recognize a tap, but you can add a button by yourself
vw.bk_(whenTapped: {
//Create and present your next viewcontroller to
})
return vw
}
return nil
}
set the footers height to 0 if there are addresses
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
if addresses.count > 0 {
return YOUR_DESIRED_FOOTER_HEIGHT_FOR_INPUT
}
return 0
}
create row for each address
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let address = addresses[indexPath.row]
let tableViewCell = UITableViewCell() //maybe you have to create your own if the layout does not fit
//set tableViewCell's title / description to show address values
return tableViewCell
}
In this case, the footer view (you can do the same in the header if you want) with the add button is shown when no addresses are available, and it is hidden, when addresses are available.
As I am new in Swift I got stuck in a situation. I am working on a app in which I want show side index section like in a contact app. I have used this code in my app
func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int) -> Int{
print(sections.index(of:title)!)
return sections.index(of:title)!
}
But this method never get called, And the TableView is not showing the side index section. I am using Swift 3. Any help will be appreciated.
I have a tableview in which country list is there now i want to focus particular section with selection of section index (A..Z). I have implemented the above code but section index is not showing.
After a long research got the solution i was doing a silly mistake. To focus on selected section we need to scroll the tableView at selected section with this code.
You can see complete code here :https://github.com/ipraba/EPContactsPicker/blob/master/Pods/EPContactsPicker.swift
override open func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int) -> Int {
// if resultSearchController.isActive { return 0 }
tableView.scrollToRow(at: IndexPath(row: 0, section: index), at: UITableViewScrollPosition.top , animated: false)
return sections.index(of: title)!
}
My UITableView contains multiple sections and I would like these sections to have different names. The titleForHeaderInSection method is provided to change the name of a section. It returns a String and it looks like this:
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return "My First Section"
}
This is great for changing one name, but what if I have multiple sections? Should I use more than one functions? Should I declare the names in some ways in the viewDidLoad or numberOfSectionsInTableView methods? They don't like the right choices, though.
How to edit multiple titles of sections in UITableViews?
Using an array of your section titles, return the correct string like so:
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
let sectionInfo = arrayOfSectionNames[section]
return sectionInfo
}