I'm creating UIViewController that contains a UICollectionView this is all setup in the storyboard, delegates and outlets I believe to be correct. In the UIViewController I have implemented the following methods:
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
In addition to the above the storyboard includes a UICollectionViewCell that is defined in a separate class. This is all working perfectly and the CollectionView is displaying data as expected.
But... I want a create a separate class that implements UICollectionViewDataSource, UICollectionViewDelegate methods and I've cut and pasted the methods from above that were in the UIViewController class into a separate datasource class. I'm then setting the UICollectionViews delegate and datasource to point to the new class. This results in the following exception :
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'UICollectionView must be initialized with a non-nil layout parameter'
I have tried adding the new class as an NSObject in the storyboard and connecting the collection view, and also programmatically in the ViewDidLoad method in the ViewController same exception with both. Also the exception is being generated before ViewDidLoad, the ViewController is the root view controller.
Am I missing something, googling suggests that the collection view initWithCollectionViewLayout is required but how is this achieved when the CollectionView is being initialized in the StoryBoard and why does it work when it's methods are in the ViewController class?
One final point this is using xCode 6 Beta 5, in a perfect world I'd try this in xCode 5 but I'm migrating the data source to Swift.
After all that typing I discovered that it was a silly typo, I'd made the datasource class a subclass of UICollectionView instead of NSObject.
Related
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.
I create a UITableView when a user presses a button, set it's delegate and data source to the current controller (which implements both UITableViewDelegate and UITableViewDataSource protocols), add it as a subview to the controller's view and implement the data source methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
Whenever I scroll the table view, the application crashes with
[UITableView currentPage]: unrecognized selector sent to instance 0x11365c00
where 0x11365c00 is the tableView. If I don't set the tableView's delegate and only set the data source, it doesn't crash. This behavior is the same if I return 0 in numberOfRowsInSection, so that nothing is added to the tableView and there is no crash related to my data. Any help would be great!
The crash occurs because you are sending a message -currentPage to an object that can't handle it.
And actually tableviews doesn't have this method in their interfaces, unless you are using a category. So the question is which object n your implementation file should handle this message?
Reason:
[someObjectHere currentPage]; // Here someObjectHere is really a table view(UITableView type)
If you have table view class and forgot to define the currentPage method, then define it there. That's y it crashed the app.
If you have currentPage method in your view controller then you have to make sure that someObjectHere is a your View controller.
[self currentPage];
I have a UITableview. One of the UITableViewCell's is a UICollectionview with instance name "amenityView". The UICollectionViewDelegate and the UICollectionViewDataSource are set in the storyboard as shown below. The following methods get called and the data is populated as expected.
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
- (UICollectionViewCell *)collectionView:(UICollectionView *)collection cellForItemAtIndexPath:(NSIndexPath *)indexPath
However, the methods below didn't get called when I select the UICollectionViewCell contained in the UICollectionView. What have I missed?
-(void) collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
-(void) collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath
UPDATE:
return YES in this method collectionView:shouldSelectItemAtIndexPath: will invoke the below two methods. At least that's what was missing on my part. Hope this will help some body...
Does the table view's didSelectRowAtIndexPath get called? If so, the table view may be intercepting the touches and not passing them through to the collection view inside. I've never done the solution you are trying to do, but the collection view is inside a scroll view, and it may not be easy to pass the touch info along to the collection view in a way that makes sense, so you may need to disable tapping on the table view cell in order for the collection view to respond to touches.
I'm trying to add (or have) a navigation bar (or items) on the top of a View controller and and a tableview right below the navigation bar. The problem I'm having is when I set the tableview's datasource to View Controller, my app will crash (setting the tableview's delegate to View controller doesn't). For now, the code for the tableview are in the default ViewController.m. Do I have the tableview's code in the right place or did I connect something improperly?
Here's the error that it gives me:
2013-10-10 15:14:48.442 SomeApp[15058:a0b] -[UIViewController >tableView:numberOfRowsInSection:]: unrecognized selector sent to instance 0x8d42450
2013-10-10 15:14:48.450 SomeApp[15058:a0b] *** Terminating app due to uncaught exception >'NSInvalidArgumentException', reason: '-[UIViewController >tableView:numberOfRowsInSection:]: unrecognized selector sent to instance 0x8d42450'
Make sure your view controller adheres to the proper protocols:
CustomViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
And add the necessary methods from these protocols to your implementation. These are the documentation links for your ease:
UITableViewDelegate Protocol Reference
UITableViewDataSource Protocol Reference
You are missing some methods that are required for your tableview to work,
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
More information on UITableViewDataSource Protocol Reference
I have a storyboard hosting a UICollectionview, in the collectionviewcontroller I implement the
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
itemViewCell *itemCell =
[collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier
forIndexPath:indexPath];
return itemCell;
}
but on the dequeueReusableCellWithReuseIdentifier the app throws this exception :
[__NSCFConstantString initWithFrame:]: unrecognized selector sent to instance 0x7443c60
So my first inclincation is to look at the custom cell I am creating, just to make sure I have an implementation for that method , and I actually do
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor whiteColor];
}
return self;
}
And of course I am registering that cell in the viewdidload
[super viewDidLoad];
[self.collectionView registerClass:[CellIdentifier class]
forCellWithReuseIdentifier:CellIdentifier];
But I don't think this is related, because I put a breakpoint on the initWithFrame method and it never hots it. What am I doing wrong.
According to the documentation:
This method dequeues an existing cell if one is available or creates a new one based on the class or nib file you previously registered.
and continuing:
Important: You must register a class or nib file using the registerClass:forCellWithReuseIdentifier: or registerNib:forCellWithReuseIdentifier: method before calling this method.
You need to implement one of those methods because dequeueReusableCellWithReuseIdentifier: forIndexPath: may need to create an object and needs the above methods to do so. Maybe you have created those and did not show them. If you have implemented one of them can you show your code?
UPDATE:
Based on your viewDidLoad and the error message you are getting it looks like CellIdentifier is an NSString. When you are calling [CellIdentifier class] you are registering a string as the use class, not a cell. You need to put the class you are using here. Based on your implementation it appears you would use [itemViewCell class].
Just so you know, you should always capitalize classes. So if itemViewCell is an actual class you should change it to ItemViewCell and property and variable names should be lower case (so cellIdentifer vs CellIdentifier).