I have two UITableViews that I want to put into my app and obviously would need to set the properties of each of them (cellforRowAtIndexPath, numberOfRowsInSection).
How would I do this with two UITableViews?
Would I put an if statement (please explain) in these methods, or are there separate ways to do this?
If you are creating by IBOutlet set tag for each UITableview in properties window then if you want to set datasource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
if(tableView.tag == 1)
{
return 1;
}
else
{
return 2;
}
}
same way set for cellforRowAtIndexpath.hope will help
Those are not "properties". They are methods; in particular, they are messages to the data source and delegate of the table view. Each table view gets to designate what object should be its delegate and data source. (Even those need not be the same object, but they usually are.)
So. If the tables are different, then why not have the data source and delegate of Table 1 be one object, and the data source and delegate of Table 2 be another object?
But if that is impossible, and both tables must have the same object as their data source and delegate, then yes, you will obviously need to distinguish one table from the other. That, after all, is what you typically do when you have a table and a search results table based on it.
To display two tables simultaneously you may be beter off creating two view controllers rather than distinguishing tableviews in a single controller. Do you really want to take small iPhone screen space displaying both the folder list and actual mail content at once? UI where controllers are pushed/popped has lots of advantages.
But if you want something different you may want to have a look at implementations of slide menu interface. That will show you how to implement two controllers visible simultaneously.
On iPad it is different and API provides a split view or master-detail interface.
Related
I've two exactly similar views which I show in a two segmented control. Refer to image below. The differences between these two views is the parameter which I send to backend to fetch the values and the title. Even the returned values are same.
I've referred to some tutorial which cycles from one view to another when segment is selected .
I've ended up with two files with exactly same code. How to optimise this implementation so that I can implement with one piece of code only.
The two contained VCs have exactly same code to fetch values from backend and display. I've only one function which I've used in both VCs to fetch but there are other code sections such as Tableview delegations and other codes which are common to both.
In storyboard both are duplicate as well.
Is there anyway I can make it more efficient?
This could be a case for making your two view controllers be subclasses of a common superclass.
Or it could be even simpler: make them two instances of the same view controller class, which knows what to do because you pass a parameter at creation time telling it what to do.
For example, my Albumen app uses four view controllers, which differ primarily just in what query they perform on the user's music library. So I've elected to make them four instances of one view controller class, with an enum property saying which query it is, and any other varying functionality determined through switch statements on that enum.
I think you need to create only 1 VC ( In IB and code ) , put all the logic inside it and either
1- Add once instance / container of it to the MainVC and manage the process of selecting a segment to reload the content ( Recommended )
2- Add 2 instances of it to the MainVC and manage hide/show when the segment is selected
I have drawn my tableView in storyBoard with static cells and multiple sections. 6 sections each has proper number of static cells. In code, in MyTableViewController I do not implement any of the datasource or delegate methods, which logically means I do not have my model in code, the array or whatever that dataSource methods will use to populate number of sections or number of rows in a section. My question is: is it possible to insert a row to any of the sections?
I read a lot of stack questions. All of them is based on having a model array or dictionary that plays its role in dataSource methods to construct the table.
I have my table already constructed in storyBoard. I can get my number of sections with tableView.numberofSections() for example. Which means the model is stored somewhere for sure. I just need a proper method to get access to that model.
There is a reason the UITableView works the way it does with the datasource protocol. It allows iOS to use just what is needed to display on the screen at any given time as you scroll through the table, making it very efficient. Without implementing the required methods, iOS will not know how to rebuild the cell if you scroll it off the screen and then back on.
If you don't need that complexity (and really, it isn't complex and you can implement the required methods in less time than it is taking me to respond), you could use a UIStackView inside of a UIScrollView. It would allow you to simply add a set of UI components vertically down the screen, complete with scrolling.
Can you explain why you don't want to implement the UITableViewDataSource protocol?
I noticed in using UITableView, UICollectionView, UIPickerView, UIScrollView, ..., and numerous other UIKit classes that the UIViewController containing the object instance often bears the role of DataSource and Delegate.
I understand from Apple's documentation what these data source and delegate methods are called, and how to implement them... for a single instance of each class.
My question is, how do you handle different instances in the same UIViewController? For example, if I have two UICollectionViews, or three UIPickerViews, ...., or fifty UIScrollViews? I can implement the data source method only once per UIViewController, but I somehow have to tell the program different instructions?
The only thing I can conceive is a gigantic switch statement or a bunch of cascading if-else if-else comparing the input to the delegate or data source method to each object instance in the UIViewController, which might get out of hand if there are many.
While we're used to using our view controller as the delegate, there's no need to do so. You can actually create NSObject subclasses that conform to the delegate protocol in question. You can then instantiate those objects and use them as the delegates of the UI objects (or whatever) as needed.
For example, consider a scene where I have two text fields, one which permits only numeric values, and one that does not accept numeric values. I can write a separate delegate object for each type of text field.
If implementing this programmatically, I would manually instantiate the two delegate objects, keep some strong references to them in my view controller, and then in viewDidLoad I can set each text field's delegate to be the appropriate delegate object.
If doing this in Interface Builder, you can actually drag an "Object" from the "Object Library" onto the scene (either in the bar above the scene or the document outline to the left of the scene):
You can then specify the class for this object:
Repeat this for all of your delegate objects:
And finally, you can go to your text field and specify the delegate by control dragging to the delegate object you added to the scene:
Doing it in Interface Builder means that it completely takes care of the instantiation of this delegate object for me and I have to do nothing in view controller's code.
Bottom line, if you want distinct behavior for a UI object, you can just instantiate a separate delegate object that manifests the desired behavior, and use that as the UI object's delegate. This pattern of instantiating separate delegate objects is common in iOS 7 custom transitions (where we have all sorts of delegate objects banging about), but can be used in this context, too.
BTW, you can obviously just subclass the UI control in question, too, and further encapsulate the logic there. That works equally well.
By creating referencing outlet for each controller,for example if you have two UITableView ,You can create outlet for each such as table1 and table2. To set number of rows in a section for these table ,you can code like follow
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == table1) {
return 10;
}
if (tableView == table2) {
return 5;
}
return 1;
}
You can create independent UIViews for each tableView or collection view with it's own .swift and .xib (and maybe if they are very similar you can reuse them). Doing that you will have the tableView and collecionView delegate methods in separated files and everything will be more clear. In your view controller you will just have to place the views, but you won't have any delegate methods there.
Well you are asking to differentiate the views with datasource & delegate in a smarter way. But you are overthinking this thing.
Everyone takes the different tableviews or pickers because they wan't be the same.
Otherwise they can be reused.
Now if they are going to be different from others then ultimately somewhere in your code you have to put the if...else or case statements. For example for tableview while setting the value of an UILabel or any value in your UITableViewCell.
If you are facing a such an issue that you have to put that many scrollviews or something in only one UIViewController then its an impossible situation if you are following the coding standards or may be your app design is faulty.
I'm in the process of creating an app that needs to have 2 TableViews that is linked to core data. The first table View is the Parent tableview wherein the user needs to select it before the 2nd table view populates with the associated data. I've been looking at examples and solutions but I came upon an issue with the FetchRequest Controller. how will it know which table to query?
I saw an example here but its not that complete. or at least, It did not gave a complete detail as to how to set the 2nd tableview's Delegate and Datasource. well, the delegate is the ViewController but what about the Datasource? how would it know which data to pull from?
I hope you guys can assist with this dilemma or at least, point me to an example.
I would use a UIViewController rather than a UITableViewController. Add two UITableViews, either in code or in a storyboard, and create two properties for them - let's say parentTableView and childTableView. Make your view controller both the delegate and dataSource for both tableViews. When you implement the relevant methods, begin by checking the tableView parameter that is passed in the method call, and provide the relevant data:
if (tableView == self.parentTableView) {
// provide data relevant to the parent...
} else { // provide data relevant to the child...
}
To provide the data for the tables, you could use one fetched result controller for the parent, and then use the parent - child relationship to derive the data for the child table view (eg. for numberOfRowsInSection for the child, you might use [self.selectedParent.children count], and so on). This will work fine, but you lose the benefits of using a fetched results controller for the child objects: automatic table sections, and automatic updates when new child objects are inserted/updated/deleted.
If you would prefer, you can use two separate fetched result controllers - one for the parent objects, and another for the child objects. Create a property for each, say parentFRC and childFRC, and then use the relevant one to provide the data in the tableView delegate methods as above. For the childFRC, you should set a predicate which limits the fetched child objects to those whose parent is the selected parent in the parentTableView. (You will need to reperform the fetch for the childFRC when the selected parent changes).
If you use the NSFetchedResultController delegate methods to keep track of changes to the data, you should again set your view controller as the delegate for both FRCs, and in your implementation of the relevant methods, check the fetchedResultController parameter that is passed in the method call to determine which object has been changed - parent or child - and update the appropriate table.
I'm building an app that presents table views in a majority of the screens. They present a handful of different table view cells, but there is one that is presented in 3/5 of the table views. This cell, which displays a video and provides an interface for users to interact with the video (like, comment, flag, delete, play/pause, etc), has a fairly large delegate with seven methods/functions.
My question is:
Would it be a best practice to set up a separate controller that would be a property of my view controller to be assigned as the delegate to the cell, or to subclass a UITableViewController with the methods already implemented?
The problems I see with the latter is that I would then have to implement a weird way to handle the data source (set up methods to return the models, always ensure that videos are stored in that array) and the former just seems a little odd to the standard MVC practice. Any advice?
Update
I began factoring out a data source to use that implements the cell's protocol. Another issue that I seem to be running into is displaying multiple cells, i.e.:
I have a searchDisplayController that displays UserCell's and VideoCell's, based on the selectedScopeIndex of the search bar. One way I could handle this is to create a dataSource for this tableView that handles both cases, or swap out data sources based on changes to the selectedScopeIndex. Are either of the two options looked down upon? Is swapping a table view's data source valid?
I solved this issue by implementing a UITableViewDataSource controller that would also handle the cell's delegates. I was able to shorten the 7 method delegate to a 3 method delegate on the data source, used to push new controllers, remove objects from the data model, and handle fading/updates.
Granted, I needed to pass reference to the UITableView, the UIView, and the UIStoryboard of the source UIViewController, but the code is much more readable and manageable.