I created a custom hierarchy of views, somewhere in this hierarchy is a UITableView, with an outlet called TableView, so i can reach it from backend code.
I want to create and push a new view to the root viewcontroller's view stack when an item in that list is selected, but i can not find any relevant events on the UITableView.
All controls were defined using Interface builder in .XIB files
Am i looking in the wrong place?
thanks in advance.
Yes, you are looking in the wrong place. To use UITableView's "events", you have to implement a UITableViewSource and assign it to your table view. The most common way to do it is in the table view's controller as a nested class:
private class MyTableSource : UITableViewSource
{
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
// Do something for the selected row
}
// Override both RowsInSection and GetCell methods!
}
You then set the MyTableSource class to the table view's Source property:
myTableView.Source = new MyTableSource();
Note that the UITableViewSource class does not exist in Objective-C. It is merely a MonoTouch class that hosts both UITableViewDataSource's and UITableViewDelegate's methods, making things a lot simpler.
The RowSelected event happens in the UITableViewSource.
Related
My app reads text files into [Card]. Each Card has a two-letter code at the front, and I break up the cards into different NSTableViews depending on that code. That lets me set the layout in IB so each group of cards has an appropriate display.
I used to have all of the controller code in a single VC, but as the number of tables grew, so did the complexity of this code. Since the views differ primarily in layout and some default settings, they can all descend from a single class. So I did:
class CardView: NSTableView, NSTableViewDataSource, NSTableViewDelegate { ...
and, for one example...
class GeometryView: CardView { ...
Then I went to IB, selected the tableview, and changed it's class to GeometryView. Now I have to set up the delegate and dataSource, and this is where I have my problem : IB will not allow me to drag either setting to either the GeometryView or CardView.
So... do the targets of these IB settings have to be a particular subclass, say NSViewController? Or is there something I'm missing that lets IB see these as targets? I didn't do anything in the original VC, it just worked. Or am I simply doing the wrong thing in IB?
In this image you can see the tableview on the far left, the custom view subclass in the helper, and the connections for the tableview on the right. Any attempt to drag from the connections to anywhere in the helper fails. Note that the two existing connections are to the former delegate VC, which is what I am trying to replace.
I'm not sure why Interface Builder won't let you connect the delegate or data source to itself, but you could do it programatically. The awakeFromNib method is probably the best place for this, as it's called after both initWithFrame and initWithCoder:
override func awakeFromNib() {
delegate = self
dataSource = self
super.awakeFromNib()
}
I am using a custom UITableView that complies to those protocols:
UITableViewDataSource
UIScrollViewDelegate
This table view is used in many places in my app. I have implemented image downloading in the background. When the user scrolls, additional images get downloaded – that's why I needed to implement the UIScrollViewDelegate methods. I definitely want to have this in this class and not in a view controller, because each of these custom table views use the same implementation of the methods.
Here is the problem. In my view controller, I need to implement the didSelectRowAtIndexPath method from UITableViewDelegate, because I need to perform a segue. But when I do that (and set the delegate to self), the UIScrollViewDelegate methods get caught by this view controller and are not propagated to the table view, because UITableView extends UIScrollView (and his delegate methods).
I have "solved" it by adding this to each of my view controller:
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
[self.bookTableView scrollViewDidEndDragging:scrollView willDecelerate:decelerate];
}
But having this same block of code (FYI this is only one of them, there are some more) on many places throughout the app isn't very good. Do you have any ideas how I could solve this?
I definitely want to have this in this class and not in a view controller, because each of these custom table views use the same implementation of the methods.
No, you do not. UITableView is a view. It should never talk to the network. That is the function of the model (or possibly a model controller). The function you're discussing has nothing to do with displaying information. It has to do with fetching information.
What you want is to the scroll view delegate methods into a custom UITableViewController and subclass your other table view controllers from that. The actual downloads, however, should be managed by your model. Your view controllers should observe the model and update as it changes.
I have solved it by using the new feature in iOS 6 – embedded view controllers. In each view controller, where I'm using this table view controller, I perform this:
self.tableViewController.tableView = self.bookTableView;
[self addChildViewController:self.tableViewController];
Where self.bookTableView is the UITableView in my view.
To perform a segue from this child TVC, you can use this:
[self.parentViewController performSegueWithIdentifier:#"Book Details" sender:selectedBook];
I have a custom view controller that has a view on the bottom half.
I would like to add a static UITableView on the top half.
So I dragged a UITableView on the view controller but apparently that is not allowed since static table views only are only embeddable in UIViewControllers.
I went to my code and made my controller extend UITableView but that doesn't fix the issue.
How do I add my static UITableView as a second view in my custom controller?
EDIT: Perhaps having a table view not taking up the whole screen is not very well supported in iOS storyboards. Maybe I will just use regular tables on a view since i just need 3 static rows.
You should be able to do something simple like this:
UITableViewController *tbv = [[UITableViewController alloc] initWithFrame:[CGRect whateverSize/Location]];
[self.view addSubview:tbv];
Be sure when doing this to also write needed delegate functions such as numberOfRowsInSection: , numberOfSections: , cellForRowAtIndexPath:, tableView:didSelectRowAtIndexPath:
Be sure to check out the UITableView Class Reference
I solved this issue by making my second view controller a simple UIViewController that implements the delegate and datasource, dragging a dynamic table on it and setting the rows and sections "statically" in code. Now I have my two views correctly cohabiting in a large view.
Is it possible to create and display a UITableView controller which allows the user to select an item and fire back a message to the delegate without subclassing it?
The reason is I just want to display a list of items in a popovercontroller and it seems a waste to have to create a subclass just for this
In the view controller that presents the popover you could implement UITableViewDataSource and UITableViewDelegate - then set the popover's tableview to use the parent controller as its source and delegate before presenting it.
If you are using iOS 5 SDK then you can make static cells.
Otherwise the only option is to create a subclass and provide a DataSource array.
Either ways you might want to have a View Controller that prepares the view controller loaded on the touch action?
I am working on a view-based project. My first view is a UIView where i fetch my data. Then i add a subview to my window which is a UITableView. Now i am unable to populate my data to UITableView. Please help..
There are two properties in UITableView, that are called delegate and dataSource. They can be bind on any object that implements specific protocol (UITableViewDelegate and UITableViewDataSource). Second object (DataSource) is what you need. It has all the callbacks for populating table rows/sections.
By default these properties are bind to a UITableViewController instance. But you can change that.
This is not something that can be easily answered in a paragraph or two. You would do well to thoroughly read through Apple's Table View Programming Guide to understand how the UITableView and its data controller and delegate methods are used. This is an excellent overview of how this class works.