First of all, I'm not sure the name of it is "extension view", please look at the screenshot, I mean the view with the yellow background.
I have made a custom table view in this view, and I did all the configurations, the problem is, in the end, I have to add delegate and dataSource for it.
Let's call the table cell inside of the view "OptionTableView".
I wrote these lines the viewdidload of the view controller (the controller that is inside the iPhone frame in the screenshot),
override func viewDidLoad() {
super.viewDidLoad()
OptionTableView.delegate = self
OptionTableView.dataSource = self
}
but it crashes the app with this error:
Thread 1: signal SIGABRT
Because it's UiView, I can't make a new file with a type of UIControlView for it.
Could you help me? How I can add delegate and dataSource for this extension UIView or whatever is called, that let me to use tableview inside it?
Thank you so much for your help
I think you not add protocol of tableview. I write a code for this:-
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var table_view: UITableView!
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
table_view.dataSource = self
table_view.delegate = self
}
}
Related
how can i respond to cell taps in static tableview? Is there a way to link it with code? I know that i can use a dynamic one but isn't it possible with a static one?
didSelectRowAt doesn't get called
Code for Selecting not working
class SettingsVC: UITableViewController, UITabBarControllerDelegate {
// MARK: - View lifecycle
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("SELECTED") // not get called
}
}
This can be done using a Static table in a UIContainerView.
Here is the Storyboard setup:
and how it looks at run-time:
When you use a UIContainerView it creates an embed segue... and that will trigger a prepare call where you can set the tableView's delegate to self (if desired).
Here's the code:
import UIKit
class EmbedTestViewController: UIViewController, UITableViewDelegate {
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// When using UIContainerView, prepare for segue will be called on load
// un-comment this block to use SELF as the delegate
// for the tableView in the embedded tableViewController
//if let vc = segue.destination as? MyStaticTableViewController {
// vc.tableView.delegate = self
//}
}
// this will only be called if .delegate is set as shown above
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("didSelectRowAt called in \"Parent\" for indexPath:", indexPath)
}
}
class MyStaticTableViewController: UITableViewController {
// this will NOT be called if .delegate is set as the "parent" view controller
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("didSelectRowAt called in \"Table View Controller\" for indexPath:", indexPath)
}
}
Note the comments and commented lines of code in the prepare func in EmbedTestViewController.
If you run this with those lines commented, didSelectRowAt will be called in MyStaticTableViewController class.
If you un-comment those lines, didSelectRowAt will be called in EmbedTestViewController class.
EDIT
Here is a full example: https://github.com/DonMag/ContainerTableView
You need to either:
Change SettingsVC to be a subclass of UITableViewController.
Make SettingsVC the delegate of your table view, since tableView(_:didSelectRowAt:) is a method of UITableViewDelegate.
So I have 2 Views that are shown inside a UIView, based on what is selected on the SegmentViewController. I create dummy data, returning 20 row of a custom cell. This works great.
Everything is fine, till I interact with the TableView.
Bellow is my code:
GoalsViewController.swift
import UIKit
class GoalsViewController: UIViewController {
#IBOutlet weak var goalsTableView: UITableView!
let goalCellIdentifier = "goalCell"
override func viewDidLoad() {
super.viewDidLoad()
goalsTableView.delegate = self
goalsTableView.dataSource = self
goalsTableView.register(UINib(nibName: "GoalsViewCell", bundle: nil), forCellReuseIdentifier: goalCellIdentifier)
goalsTableView.reloadData()
}
}
extension GoalsViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 20
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = goalsTableView.dequeueReusableCell(withIdentifier: goalCellIdentifier, for: indexPath) as! GoalsViewCell
cell.goalTitle.text = "aaaaa"
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("Selected \(indexPath.row)")
}
}
After any of the empty rows is selected, the didSelectRowAt is not called, so the cells are not there at all. I tried to find a solution, but I was only to find issues about empty lists, before being populated.
What could be the reason for the empty tableview?
I might be wrong here but one thing that I've noticed is that you are not implementing a function which sets the height of each cell.
// Specify the height of your cells
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100 // Or your given cell height.
}
So here is my theory: If you are using constraints something is missing and your cell's height can't be identified by constraints alone or you are not using constraints at all thus you must use heightForRowAt function to specify each cell's height.
I will explain what was the issue for people who probably did not know (like me).
So my UITableView is inside a UIView that changes based on what the user is selecting. In total I had 2 different Views that where switching. The reason that it was emptying it was because my parent ViewController, could not access the delegate for UITableView. To fix that, after adding a subview to the UIView, you need also to move the ViewController to the parent controller. In code it goes like this.
// Empty array of UIViewControllers
var views: [UIViewController]!
// Add the UIViewControllers to the array
views = [UIViewController()]
views.append(EventsViewController())
views.append(GoalsViewController())
for view in views {
// Needed to adjust the size of Subview to size of View
view.view.frame = containerView.bounds
// Add the subviews
containerView.addSubview(view.view)
}
// Bring the view in position 1 to the front of the UIView
containerView.bringSubviewToFront(views[1].view)
// Add Views[1] UIViewController as a child to the parent controller
self.addChild(views[1])
views[1].didMove(toParent: self)
// After done with everything with the UIViewController remove it
views[1].removeFromParent()
addChild Apple.com
didMove Apple.com
This question already has an answer here:
UIView - How to get notified when the view is loaded?
(1 answer)
Closed 5 years ago.
I am currently creating a custom view. This view has a UITableView with it. The delegate for this control will be the backing class for the custom control.
class MyView: UIView {
#IBOutlet weak var autoCompleteView: UITableView!
}
extension MyView: UITableViewDelegate {
}
extension MyView: UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath as IndexPath)
cell.textLabel!.text = "\(indexPath.row) - Its working"
return cell
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
}
Now at some point here, in this class, I need to get the delegate for the UITableView but that can only happen once the view has been loaded (otherwise autoCompleteView will be nil).
If it were in a UIViewController I could simply add it to viewDidLoad but I dont have that open here. So how can I go about setting the delegate for the UITableView
Now at some point here, in this class, I need to get the delegate for the UITableView but that can only happen once the view has been loaded
I am not entirely sure what you mean by that. The view MyView is loaded if you are inside a method of it. If the class would not be there, it could not be calling a method of it. So if you configure things in initWithFrame: everything should be fine.
The only thing I can think of otherwise is if your view is layed out in Interface Builder and thus will be decoded. In that case, while the view might already be loaded, some references might not be. For this, you will get a call to awakeFromNib after all decoding has completed.
//you can try these
class MyView: UIView {
#IBOutlet weak var autoCompleteView: UITableView!
override func willMove(toSuperview newSuperview: UIView?) {
super.willMove(toSuperview: newSuperview)
}
override func didMoveToSuperview() {
super.didMoveToSuperview()
}
}
This question seems to have been asked many times on StackOverflow, but after searching for hours, I still haven't found the solution to my issue.
I have a table view in SecondViewController.swift and I did make it delegate and dataSource SecondViewController.swift, but the didSelectRowAt method is still not fired when a table cell is clicked. I am trying to apply a segue to another view controller, but the didSelectRowAt method isn't working itself.
I have selected Single Selection in my storyboard in the table view properties, and I have made sure that user interaction is enabled for the table view and the prototype cell.
For the SecondViewController.swift below, please assume that allEvents are populated into the allEvents array. I was able to successfully populate them and display them in the table. The only problem is clicking on the row to perform a segue. Also, please ignore the awkward indentation below.
SecondViewController.swift
import UIKit
class SecondViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var tableView: UITableView!
var allEvents: Array<JSON> = []
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
//self.tabBarItem.image = myTabImage
self.tabBarController?.tabBar.isTranslucent = false
self.tabBarController?.tabBar.barTintColor = UIColor(red:0.25, green:0.25, blue:0.25, alpha:1.0)
self.tabBarController?.tabBar.tintColor = UIColor.white
//ASSUME ALL EVENTS ARE POPULATED INTO allEvents
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: Tableview Datasource
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return allEvents.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 150
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("SEGUE")
self.performSegue(withIdentifier: "oneSegue", sender: allEvents[indexPath.row])
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "eventViewTableCell", for: indexPath) as! EventViewTableCell
return cell
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// let detailController = segue.destination as! EventDetailsController
}
}
I have been on this for hours and still have not found out the problem. I would greatly appreciate any help!
You may want to check your tableview again, do choose single selection.
I'm assuming you are selecting No Selection as the picture bellow
Hope it helps.
I had the same problem on a Controller within a TabBarController.
What fixed it for me was this:
Disable the User Interaction for the Content view
My guess is that it was becoming the responder so it removed the event from the TableView
Note: Since the viewDidLoad assignments to delegate and dataSource became redundant after setting it up in the StoryBoard, I removed them, although leaving them does no harm.
If you do nothing else than calling the segue in didSelectRowAt remove the entire method and connect the segue in Interface Builder to the table view cell (rather than to the controller). The sender parameter will contain the reference to the selected table view cell.
I suspect when you collected and populated your allEvents array did you collect any touch events in there ?
or have you used UIGestureRecognizer in this or it's super view ?
If you have intercepted any touch event to populate your array or any other purpose comment it out and test it with a simple preloaded array like :
let dataSource = ["1", "2", "3", "4"]
let me know if this is not your case so I can find another solution.
Numerous tutorials I've been through say the only code I need to display the array I want it to is:
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var chatListTableView: UITableView!
var friends = ["Anthony", "Antonio", "Andy"]
override func viewDidLoad() {
super.viewDidLoad()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return friends.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell : UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "ChatListCell")
cell.textLabel.text = self.friends[indexPath.row]
return cell
}
}
However, when I run the app, the tableView is still blank. What am I doing wrong? I feel that I am missing something.
All I want to do is display the array in the tableView.
Check if the ViewController is the datasource and delegate of the tableview
As Aci says in his answer, you have to set the data source and delegate of the table view to your view controller. The easiest way to do that is in Interface Builder.