I have a UITableViewController subclass with sections. The sections are showing with the default style (no rounded corners). How can I set the TableView style to grouped in the code? I'm not using Interface Builder for this, so I need something like
[self.tableView setGroupedStyle]
I searched on Stack Overflow, but couldn't come up with an answer.
You can do the following:
UITableView *myTable = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
Swift 3:
let tableView = UITableView.init(frame: CGRect.zero, style: .grouped)
If i understand what you mean, you have to initialize your controller with that style. Something like:
myTVContoller = [[UITableViewController alloc] initWithStyle:UITableViewStyleGrouped];
I give you my solution, I am working in "XIB mode", here the code of a subclass of a UITableViewController :
-(id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithStyle:UITableViewStyleGrouped];
return self;
}
Below code Worked for me, I am also using UITableview class
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:UITableViewStyleGrouped];
if (self)
{
}
return self;
}
If you are inheriting UITableViewController, you can just init tableView again.
Objective C:
self.tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
Swift:
self.tableView = UITableView(frame: CGRect.zero, style: .grouped)
Setting that is not that hard as mentioned in the question. Actually it's pretty simple. Try this on storyboard.
Swift 4+:
let myTableViewController = UITableViewController(style: .grouped)
Swift 4
Using Normal TableView
let tableView = TableView(frame: .zero, style: .grouped)
Using TPKeyboardAvoidingTableView
let tableView = TPKeyboardAvoidingTableView(frame: .zero, style: .grouped)
If you create your UITableView in code, you can do the following:
class SettingsVC: UITableViewController {
init() {
if #available(iOS 13.0, *) {
super.init(style: .insetGrouped)
} else {
super.init(nibName: nil, bundle: nil)
}
}
#available(*, unavailable)
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
For set grouped style in ui itself:-Select the TableView then change the "style"(in attribute inspector)) from plain to Grouped.
You can also do this if you want to use it on a subclass you've already created in a separate swift file (probably not 100% correct but works)
override init(style: UITableViewStyle) {
super.init(style: style)
UITableViewStyle.Grouped
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
Now in you appdelegate.swift you can call:
let settingsController = SettingsViewController(style: .Grouped)
You can do this with using storyboard/XIB also
Go To storyboard -> Select your viewController -> Select your table
Select the "Style" property in interface-builder
Select the "Grouped"
Done
If you have one TableView for more tables, and one of this tables is grouped and the another one plain, than you can simulate the plain style with the function from UITableViewDelegate:
override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return CGFloat.min
}
swift 4
if you don't want use storyboard, this might be help.
you can add table view and set properties in a closure:
lazy var tableView: UITableView = {
let tableView = UITableView(frame: .zero, style: .grouped)
tableView.backgroundColor = UIColor(named: Palette.secondaryLight.rawValue)
tableView.rowHeight = 68
tableView.separatorStyle = .none
tableView.translatesAutoresizingMaskIntoConstraints = false
return tableView
}()
then add in subview and set constraints.
If you're not using Storyboards and just want a clean, concise way to setup your UITableViewController subclass to use a different tableView style, you can simply override loadView like this:
override func loadView() {
let tableView = UITableView(frame: .zero, style: .grouped)
tableView.delegate = self
tableView.dataSource = self
view = tableView
}
As the documentation says:
loadView creates the view that the controller manages
it's a method you can ovveride when using ViewControllers whose views are not defined via Storyboards or NIBs.
The UITableViewController implementation already overrides this method for you to crate a simple, plain UITableView as the root view for the controller, but nothing stops you from further overriding it to create a table view that better suits your needs.
Just remember:
Your custom implementation of this method should not call super.
You can also try to make the separator line color clear which could give the grouped style effect:
[myTVContoller.tableView setSeparatorColor:[UIColor clearColor]];
You can use:
(instancetype)init {
return [[YourSubclassOfTableView alloc] initWithStyle:UITableViewStyleGrouped];
}
self.tableView.style = UITableViewStyleGrouped
EDIT:
Had assumed this was a read/write property. In that case, you can either follow Dimitris advice and set the style when you instantiate the controller, or (if you're using a XIB), you can set it via IB.
Related
I attempted a bunch of answers on here with no luck.
I am attempting to reload my collectionview within my custom cell after fetching data from firebase. I am unable to even get the print statement to show from the custom cell. Not sure what I'm doing wrong.
On my ViewController I have the following delegate and call, I made a button to test to see if the delegate print statement on my custom cell will appear but no luck.
protocol DiscoverControllerDelegate {
func didFetchData()
}
class DiscoverController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
let cellId = "cellId"
let headerId = "headerId"
let database = FirebaseData.sharedInstance
var delegate: DiscoverControllerDelegate?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
title = "Discover"
collectionView?.backgroundColor = .white
collectionView?.register(CategoriesCell.self, forCellWithReuseIdentifier: cellId)
collectionView?.register(HeaderCell.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: headerId)
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Refresh", style: .plain, target: self, action: #selector(reloadData))
database.retrieveData {
print("fetching data")
self.delegate?.didFetchData()
}
}
#objc func reloadData () {
print("attemping to reload")
self.delegate?.didFetchData()
}
*edit to add on my override init
On my custom cell:
class CategoriesCell: UICollectionViewCell, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, DiscoverControllerDelegate {
let itemCollectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.backgroundColor = .clear
return collectionView
}()
func didFetchData() {
print("RELOADING NOW!")
itemCollectionView.reloadData()
}
override init(frame: CGRect) {
super.init(frame: frame)
itemCollectionView.dataSource = self
itemCollectionView.delegate = self
itemCollectionView.register(ItemCell.self, forCellWithReuseIdentifier: cellId)
itemCollectionView.reloadData()
createLayout()
}
Many things wrong here. The reason "RELOADING NOW!" never logs is because you never set the delegate in your view controller. If you inspect self.delegate in DiscoverController it is probably nil. However, your entire setup right now seems flawed unless I'm misunderstanding what you're doing.
What does your UI look like? Why does CategoriesCell have a UICollectionView property? It's itemCollectionView property doesn't even have a datasource or delegate set and its not an #IBOutlet yet you're calling reloadData() on it. Not sure what it's even displaying or what you're tyring to do.
I feel like there is probably a lot more wrong here than just a single thing. You probably want to go through some UITableView and UICollectionView tutorials to learn about delegates and datasources in iOS.
I dont know about collection view but I use similar protocol structures with a table view. They are not much different. your protocol should be in the cell class not in the controller.
I've gone through the steps for a table view in the following post:
Firebase update
Maybe you can adapt it for your needs...
I want to remove the line between 2 views. The line that separates 2 UITableViewCells:
I declared table view as following:
self.tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
self.tableView.delegate = self;
self.tableView.dataSource = self;
self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
self.tableView.scrollEnabled = NO;
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
self.tableView.estimatedRowHeight = 85.0;
self.tableView.rowHeight = UITableViewAutomaticDimension;
So i actually wrote - self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
Why does it still exist?
Objective-C :
[self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
Swift:
self.tableView.separatorStyle = UITableViewCellSeparatorStyle.None
Swift 5.0 renamed it in :
self.tableView.separatorStyle = UITableViewCell.SeparatorStyle.none
Apply the line in viewDidLoad() method.
If you want to do it from nib file, set the tableView's Separator property to None
For Swift 4:
tableView.separatorStyle = .none
For Swift 5 :
viewDidLoad(){
tableView.separatorStyle = UITableViewCell.SeparatorStyle.none
}
For Objective-C :
[self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
or you can use interface builder instead
For more information
SeparatorStyle
Hide tableView separators using UI
Here you select TableView 'Separator' property as 'None'.
https://i.stack.imgur.com/8KyH5.png
You can use the following code because it will not remove the line separators of the sections.:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Your code here //
cell.separatorInset = UIEdgeInsetsMake(0.f, [UIScreen mainScreen].bounds.size.width, 0.f, 0.f);
}
My problem was when I add tableView trough code and I have separate func to show tableview and add it on mainView (slide from bottom) I needed to add this
tableView.separatorStyle = .none
in that func where tableView is added on mainView and constraint it.
In Swift 4.2 you can conveniently use dot notation on a tableView's separatorStyle. Like so:
tableView.separatorStyle = .none
As #gonsee point out:
"Setting separatorStyle seems to have no effect unless the table view is in the window's view hierarchy. If you have a table view on some UIView subclass"
You should set the seperatorStyle in viewDidAppear if you your table in UIView.
override func viewDidAppear(_ animated: Bool) {
self.contentView.documentTableView.separatorStyle = .none
}
In viewDidLoad add tableView.separatorStyle = .none
Example:
override func viewDidLoad() {
super.viewDidLoad()
...
self.tableView.separatorStyle = .none // <---
...
}
you can archive these things in different ways
you can also use this one line of code in viewDidLoad()
override func viewDidLoad() {
super.viewDidLoad()
tableView.tableFooterView = UIView()
}
You can do it on a storyboard
set the code in viewDidLoad()
override func viewDidLoad() {
super.viewDidLoad()
tableView.separatorStyle = .none
}
add this line
tableView.separatorStyle = .none
What I want to do is display a UICollectionView inside a UICollectionViewCell when this cell is selected. I want to use rbcollectionviewinfofolderlayout to fold out my collection view and show a new collection view inside of this. However I'm not sure how I can implement this into my existing code. I have three collection views inside one view. I hide and unhide my views accordingly to what selection the user makes. I use a custom cell xib for the cells inside my collection views and I have a custom collectionviewflowlayout that makes sure there are always 3 cells showing in the width of the device.
This is what my view controller looks like.
in my viewDidLoad I have to set the RBCollectionViewInfoFolderLayout to my collectionview. As you can see the layout variable holds my CustomCollectionViewFlow which I set as the collection view layout before I implemented the RBCollectionviewinfofolderlayout.
override func viewDidLoad() {
super.viewDidLoad()
musicLib.loadLibrary()
PlaylistCollectionView.indicatorStyle = UIScrollViewIndicatorStyle.White
AlbumCollectionView.indicatorStyle = UIScrollViewIndicatorStyle.White
ArtistCollectionView.indicatorStyle = UIScrollViewIndicatorStyle.White
layout = CustomCollectionViewFlow()
cview = ArtistCollectionView
let lay: RBCollectionViewInfoFolderLayout = ArtistCollectionView.collectionViewLayout as! RBCollectionViewInfoFolderLayout
lay.cellSize = CGSizeMake(80, 80)
lay.interItemSpacingY = 10
lay.interItemSpacingX = 0
let nib = UINib(nibName: "CollectionViewCell", bundle: nil)
cview.registerClass(UICollectionReusableView.self, forSupplementaryViewOfKind: RBCollectionViewInfoFolderHeaderKind, withReuseIdentifier: "header")
cview.registerClass(UICollectionReusableView.self, forSupplementaryViewOfKind: RBCollectionViewInfoFolderFooterKind, withReuseIdentifier: "footer")
cview.registerClass(collectionViewFolder.self, forSupplementaryViewOfKind: RBCollectionViewInfoFolderFolderKind, withReuseIdentifier: "folder")
cview.registerClass(RBCollectionViewInfoFolderDimple.self, forSupplementaryViewOfKind: RBCollectionViewInfoFolderDimpleKind, withReuseIdentifier: "dimple")
ArtistCollectionView.collectionViewLayout = lay
ArtistCollectionView.registerNib(nib, forCellWithReuseIdentifier: "item")
ArtistCollectionView.dataSource = self
ArtistCollectionView.delegate = self
PlaylistCollectionView.collectionViewLayout = layout
PlaylistCollectionView.registerNib(nib, forCellWithReuseIdentifier: "item")
PlaylistCollectionView.dataSource = self
AlbumCollectionView.collectionViewLayout = layout
AlbumCollectionView.registerNib(nib, forCellWithReuseIdentifier: "item")
AlbumCollectionView.dataSource = self
}
My CustomCollectionViewFlow looks like this
class CustomCollectionViewFlow: UICollectionViewFlowLayout{
override init(){
super.init()
setupLayout()
}
required init?(coder aDecoder: NSCoder){
super.init(coder: aDecoder)
setupLayout()
}
override var itemSize: CGSize {
set {
}
get {
let numberOfColumns: CGFloat = 3
let itemWidth = (CGRectGetWidth(self.collectionView!.frame) - (numberOfColumns - 1)) / numberOfColumns
return CGSizeMake(itemWidth, itemWidth)
}
}
func setupLayout() {
minimumInteritemSpacing = 0
minimumLineSpacing = 0
scrollDirection = .Vertical
}
}
I will hold of on putting all my coding here as it will be become to big of a post and the other methodes are kind of irrelevant at this point. However what I did do is put the example application that I made for this on git here for anyone who wants to check it out.
This image shows what the state of my collectionview was before I implemented the rbcollectionview. The second image shows what I'm trying to achieve
This is how the view should look when an item is being tapped
EDIT
I have been able to get it working kind of. I was able to show the layout like I desired. Just like I had it before I implemented the rbcollectionviewinfofolderlayout. However it seems that when the folder is bigger then the screen size it won't actually fold out. It will fold out for a second and collapse again. It might be caused by the layout i've implemented. Below is the code that is responsible for this.
the class that is responsible for my layout
class RBCollectionLayout: RBCollectionViewInfoFolderLayout
{
var view: UIView!
init(view: UIView){
super.init()
self.view = view
setupLayout()
}
override init(){
super.init()
setupLayout()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setupLayout()
}
func setupLayout(){
let numberofItems: CGFloat = 3
let itemWidth = (CGRectGetWidth(view.frame)) / numberofItems
cellSize = CGSizeMake(itemWidth, itemWidth)
interItemSpacingX = 0
interItemSpacingY = 0
}
}
The method that will calculate the desired with when the screen is changed from portrait to landscape
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
if(view_artist.hidden == false){
guard let ArtistFlowLayout = ArtistCollectionView.collectionViewLayout as? RBCollectionViewInfoFolderLayout else {
return
}
lay = RBCollectionLayout(view: self.view)
ArtistCollectionView.collectionViewLayout = lay
ArtistFlowLayout.invalidateLayout()
}
}
this is how the layout is being set in my viewdidload
lay = RBCollectionLayout(view: self.view)
ArtistCollectionView.collectionViewLayout = lay
again all my code is available on my git here
Well, I'm probably the only person who can answer your question, since I wrote this control and I doubt anyone else is actually using it.
You seem to be missing a key component which is the delegate method collectionView:viewForSupplementaryElementOfKind:atIndexPath: where you tell the CollectionView what views to use for the various elements. If you go to the GitHub Repo and look at the example you will see that in that method I return 4 different views depending on the viewKind that was asked for. In your code I believe what you want to do is return your custom flow layout based collection view for the RBCollectionViewInfoFolderFolderKind. This would place your 3 cell flow layout view into the expanded folder of the selected cell.
I cloned your repo but it doesn't appear to be up to date with the code you are showing here.
I want to change the uitableview's stype in viewdidiload in swift.
but it gives an error "Can not assign the result of this expression
#IBOutlet weak var tableview: UITableView!
let names = ["Gulshan","Mitesh","Rahul","roma"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any xadditional setup after loading the view, typically from a nib.
tableview.style = UITableViewStyle.Grouped
}
You can do that while initializing in init with frame method.
See example:
var tableview1 = UITableView(frame: CGRectMake(0, 0, 160,320), style: UITableViewStyle.Grouped)
You can't change the tableview style dinamically, you have to do it in your xib file or storyboard if you have one.
If you don't use a storyboard or a xib, and prefer to create the tableview programmatically, specify the style while creating the tableview using the
- initWithFrame:style: method.
Bye
D.
I've created an UITableView with UITableViewCell. Between the view cells there are grew lines. I want to delete these lines and don't want to show them, but I don't know how.
I work with Xcode 6.1 and Swift.
Here is a screenshot that displays my screen:
THX!
Using Objective-C, we have:
[self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
for Swift 3:
self.tableView.separatorStyle = .none
for Swift 2:
self.tableView.separatorStyle = UITableViewCellSeparatorStyle.None
OR:
if you are using the InterfaceBuilder, you can set the tableView's Separator property to None
Within InterfaceBuilder you can set the Separator property to None or do it programmatically by setting the property separatorStyle of your table view to UITableViewCellSeparatorStyleNone.
Swift 3:
tableView.separatorStyle = UITableViewCellSeparatorStyle.none
You can do it from storyboard like this;
Swift 5 Programmatically
private func buildTableView() -> UITableView {
let tableView = UITableView()
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.separatorStyle = .none
return tableView
}
Swift 5 :
cell.selectionStyle = UITableViewCell.SelectionStyle.none
tableView.separatorStyle = .none
when initializing the tableview. It can be set or through the storyboard or nib
If you are setting up a lazy tableView, you may want to change the color to clear, seems like an Apple bug where sometimes the style is replaced on layout cycles.
private lazy var tableView: UITableView = {
let table = UITableView(frame: self.view.bounds, style: .insetGrouped)
table.separatorStyle = .none // <- HERE
table.separatorColor = .clear // <- HERE
table.delegate = self
table.dataSource = self
table.estimatedRowHeight = UITableView.automaticDimension
table.register(UITableView.self, forCellReuseIdentifier: "MyCell")
return table
}()