So i've been working on an ePub framework called Readium and they recently created an SDK for IOS.
The SDK is a full working project that allows a user to select an ePub from a tableView list and after selecting one gives you meta-data about that ePub after which you have to select the page list or spine items and after selecting one of the pages it finally goes to the ePub.
I want to streamline this process by opening with a list of ePubs in a collectionView and after selecting an ePub make it go straight to the first/cover page of that ePub.
What I want to know is if it is possible to use the viewController and data sources of the tableView to create a new collectionView? I have already adapted this project to allow Swipe Navigation.
It is possible to do it quite quickly.
1) You have to tell the controller that you want to adapt collection view, so you have two options in your .h file:
a) If you are currently inheriting from UITableView - inherit your ViewController from UICollectionViewController:
#interface YouViewControllerName : UICollectionViewController
b) If you inherit from UIViewController, just set your controller conforming to CollectionView delegate and dataSource methods like this
#interface YouViewControllerName : UIViewController <UICollectionViewDelegate, UICollectionViewDataSource> { ... }
2) Then you need to replace table view delegate and data source methods with collection view data source and delegate methods, so you need to replace something like this:
Old:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath { ... }
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { ... }
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { ... }
New:
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath { ... }
- (NSInteger)collectionView:(UICollectionView *)collectionView
numberOfItemsInSection:(NSInteger)section { ... }
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { ... }
So the content within your previous delegate/datasource methods could remain same, as the logic is not needed to change.
You may need to implement some more specific methods and to have some work with designing right item cell sizes etc., but is is natural as your layout is replaced by collection view.
Related
I have the following header file
#interface Menu : UITableViewController;
and the following m file
#import "Menu.h"
#implementation Menu
+ (void)initialize {
// TODO here I want to add cells to my table view
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)newIndexPath{
[tableView deselectRowAtIndexPath:newIndexPath animated:YES];
//my logic goes here
}
#end
I want to be able to add cells to my tableview in initialize method, how can I do that ??
To add cells to you table, you must implement the delegate and data source methods.
- tableView:cellForRowAtIndexPath: Will create and return a cell for the specified index path, which itself is basically a section and row number.
- tableView:numberOfRowsInSection: Specifies the number of cells to be in the table.
You can see the documentation here.
There is a good tutorial here.
i am new to iOS, this may seem like a basic question. I have been working through this tutorial and I have no idea how the tableview is connected to the code. The sample project can be downloaded here.
I was my understanding that you need to extend UITableViewDelegate, UITableViewDataSource in the code, then in the storyboard you can drag from the tableview to them.
But what is perplexing is that the sample project does not extend UITableViewDelegate, UITableViewDataSource at all, therefore, how is the tableview in the story board connected to the code ?
Datasource is used to supply data and delegate is used to supply behaviour. UITableView asks your datasource every time it needs data to display. It provides a lot of flexibility for how you choose to represent your underlying data model. You simply define specific methods to use in order to get table information, and iOS can call them when it needs to know something like the number of rows in a section, or the content of a particular row.
You will probably implement your own delegate mechanism in the future. It is a great design pattern which handles interaction/data transfer between objects.
Because, the basic class adopts from UITableViewController
#interface WTTableViewController : UITableViewController
In your storyboard you just ctrl-drag from tableview to viewController and choose delegate and dataSource.
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableViewDataSource_Protocol/ you should refer this it will help u alot
If you working with TableViewController, UITableViewDelegate and UITableViewDataSource are connected to table automatically. In case you are working with ViewControler which contains TableView, you have to add UITableViewDelegate and UITableViewDataSource like this: #interface myViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>. In new versions of Xcode you can drag delegate and data source to table, and if you want to set delegate programmatically, you can add this two lines of codes:
[tableView setDelegate:self];
[tableView setDataSource:self];
or, equally:
tableview.delegate = self;
tableview.dataSource = self;
In viewcontroller.h file e
declare the delegate and datasource method.
UIViewController<UITableViewDataSource,UITableViewDelegate>
then
connect the delegate and datasource method with viewController so
in viewController.m file
- (void)viewDidLoad {
tableview.delegate=self;
tableview.dataSource=self;
}
In Objective-C/iOS you often implement things by having classes conform to protocols rather than subclassing classes. WTTableViewController conforms to the protocols
UITableViewDataSource: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableViewDataSource_Protocol/
and
UITableViewDelegate: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableViewDelegate_Protocol/
In MainStoryboard.storyboard you can see in the inspector to the right that the TableViewController has a custom class of WTTableViewController
The relevant methods in WTTableViewController.m:
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"WeatherCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
}
Here's some general info about protocols: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/WorkingwithProtocols/WorkingwithProtocols.html
I suggest reading a beginners book or tutorial on iOS to pick up the overall design principles otherwise many things can be quite confusing.
I am running into a strange problem regarding Uitableview cells in Xcode 6 iOS8. When I create a tableViewController from storyboard and choose static cells, the view shows up as it suppose to. However, when I connect that same view to a TableViewController source, the cells disappear. I connected all necessary things (reusable cell_ID, etc). Anyone experience this? This used to work for me previously. Thanks in advance!
Make sure that you don't implement any of UITableViewDatasourceDelegate methods in your TableViewController such as these methods below.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
}
I have a problem where my table view does not show the delete button on cell swipes.
I created a separate datasource class that conforms to the UITableViewDataSource protocol. I have a UITableViewController that I am presenting using a UIPopoverPresentationController. Before presenting it, of course, I set up the datasource with all the information it needs and I ensure that it implements:
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return YES;
}
In my UITableViewController subclass, I also am sure to implement both:
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewCellEditingStyleDelete;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
// do something (this doesn't get hit yet anyway, as delete button does not appear)
}
}
The problem seems to be that the method tableView:editingStyleForRowAtIndexPath: does not ever get called. However, if I bypass my separate datasource class and simply implement the datasource within my UITableViewController subclass, I notice that this method does get called.
I would prefer to figure out why it is the case that my using a separate datasource class gives me problems for swipe-to-delete, rather than abandoning this class (which I am using throughout my app in non-editable table views) and instead opting for keeping the datasource within the UITableViewController subclass entirely. Any pointers on where to look would be greatly appreciated!
You need to add the following tableView datasource method in your .m file.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;
I have one parent class with one tableview.
That class is the delegate and datasource of that tableview as well.
Now I subclassed (derived) that class and made a child class.
I have one tableview in child class too.
Then I defined delegate and datasource functions in that child class, but it overrides parent class tableview data source/delegate methods.
But I want both of them to be separate.
However my Requirement is as Follows :
I want to retain a search bar and side button, on the top of all the viewControllers that search bar includes , a recent searches terms table underneath that.
So i thought of defining parent class for that and subclass other viewControllers from that class.
Am i doing it the right way ?
I assume you are talking about a view controller class. If I understood you right, then you are about to mess it up. Delegation is a way to avoid subclassing. Of course you can subclass the delegate - no problem. But you want a table view in the super class that owns a table in its view. And you want a subclass that has another table in its view plus the table that the superclass owns.
That is not impossible. But from your subclass' point of view, your subclass owns two table views. Even that is possible. Your view controller is the delegate of two tables (regardless of where in the view hierarchy they are declared and instanciated). When you now override the delegate and data source methods theny your subclass must either:
Determine which table it is dealing with/being called from. And then serve both tables appropriately.
Determine wich table it is dealing with/being called from. And then serve "its own" table appropriately and calls [super sameMehtod:withSamePamaters] to ensure that the superclas can still provide the data and server as delegate.
Which of both is smarter depends on the context and what you are about to achieve in detail.
A way of determinnig which table's delegate was called can be done by tagging the table views (do not use 0 as tag) or by comparing the tableView parameter of the delegate method with the corresponding properties (IBOutlets in this case). (In other cases you can compare the sender parameter with the IBOutlets. But tagging is probably easier to understand when reading the code later.)
Let's look at an example of the UITableViewDataSourceDelegat:
Your superclass implements:
#interface MySuperTableViewController:UITableViewController <UITableViewDelegate>
// There will be something in here.
// But it inherits self.tableView from UITableViewController anyway. We leave it with that.
#end
#implementation MySuperTableViewController
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// This method creates or re-uses a cell object and sets its properties accordingly.
}
#end
And your subclass:
#interface MySubTableViewController : MySuperTableViewController // no need to declare the delegate here, it is inherited anyway
#property (weak, nonatomic) IBOutlet UITableView *mySecondTableView; // self.table will be used by the superclass already.
#end
#implementation MySubTableViewController
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if (tableView == self.table) { // This call refers to the one talbe that is managed by super
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}
// This method now creates or re-uses a cell object and sets its properties accordingly.
// You may want to check wether tableView == self.mySecondTableView etc.
}
#end
(This comes from scratch, not syntax checked etc. Do not expect this to run properly right away :)
BUT ... please re-consider your class structure. I am afraid you are getting lost in some rather unlogical class hierarchy. There is nothing wrong with having two talbes managed by a common view controller even without this subclassing-thing. And there is nothing wrong with using multiple tables in a view where each of the tables has its own delegate (can be a view controller). Since iOS 5 (or was it introduces with 6) we can use the UIContainerView for that purpose and nicely build it up in IB/storyboard.
try this,
ViewController.h
IBOutlet UITableView *firstTable;
IBOutlet UITableView *secondTable;
ViewController.m
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
if (tableView == firstTable) {
return 1;
}
else if(tableView == secondTable)
{
return 1;
}
return 0;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
if (tableView == firstTable) {
return [arrItems count];
} else if(tableView == secondTable)
{
return [arrData count];
}
return 0;
}
etc etc ....