Nested CollectionView in Storyboard - ios

I have a collectionView with cell and then again a collectionView in this cell. This child collectionView is again having a cell in it. Now i want to communicate with the cell in my child collectionView from the parent collectionView. How to do that in swift 3 in storyboard? As shown in the image attached I want to communicate from first collectionView to the radio cell

In your main ViewController.swift conform it to the protocols UICollectionViewDataSource, UICollectionViewDelegate.
Now from your storyboard take an outlet of your parent CollectionView to your ViewController.swift.
Then create a Cocoa Touch Class which is subclass of UICollectionViewCell for your custom cell of UICollectionview and take an outlet of your child CollectionView in this class.
Now go to your storyboard and select your parent Collectionview cell and set its class to your custom cell class and then set an Identifier for this cell in Attributes inspector.
Now again create class for your child UICollectionview cell and do the same as parent UICollectionview.
Now everything is setup in your storyboard. After this you should write the code for your procedure in delegate methods of UICollectionView.
Now in your ViewController.swift file write the delegate methods of UICollectionView.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
let cell =
parentCollectionViewOutlt.dequeueReusableCell(withReuseIdentifier: "parentcell", for: indexPath) as! ParentCollectionViewCell
cell.childCollectionView.reloadData()
return cell
}
Now in your parent CollectionView cell class file:
Also conform it to the protocols UICollectionViewDataSource, UICollectionViewDelegate and write all delegate methods for UICollectionView and then write following code as:
override func awakeFromNib() {
super.awakeFromNib()
childCollectionView.delegate = self
childCollectionView.dataSource = self
childCollectionView.reloadData()
}
Now here in cellForItemAt() method do the same procedure for taking cell of your child CollectionView by specifying its identifier and then do your code in it and return your cell. Here you can do whatever you want to do in your child CollectionView's cell that means you have an access to your child CollectionView's cell in this class for custom cell of your parent CollectionView.

Follow this link
https://ashfurrow.com/blog/putting-a-uicollectionview-in-a-uitableviewcell/
In this tutorial the same scenario is being explained just one change
adding UICollectionView in UITableViewCell.
Go through this above link , and try to implement. It will help you

Related

iOS Use multiple CollectionView reusing the same cell

I'm new to iOS programming but from my experience with Android i know that you can create one design for a item that can be reused in multiple lists, without needing to create a copy.
In iOS i have been trying the same approach with UICollectionView.
In my view i have created three Horizontal UICollectionViews (with different data sets) which in turn use their own cell (Which is identical to the others). I don't know how to make the other two collections use the first ones cell, so i don't need to recreate the same cell over and over.
You can't achieve this using single storyboard. If you want to use Interface Builder (xml) file for layout, you should create MyCell.xib file, then drag UICollectionViewCell on that file and work with that xib.
Then you should connect .xib file with your collection view like this:
let nib = UINib(nibName: "MyCell", bundle: nil)
collectionView?.register(nil, for: "MyCellReuseID")
And you can work with your cell now.
Also you can create MyCell: UICollectionViewCell class without creating .xib file, create views on it programmatically and then call collectionView?.register(MyCell.self, for: "MyCellReuseID")
In your function collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell you can inform your collectionview which cell to use
if you have define your cell you might have something similar to this
class MyCell: UICollectionViewCell{
var Label: UILabel!
var imageView: UIImageView!
}
so into your function collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) you need to inform your collectionview which cell to use
collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell:MyCell = collectionView.dequeueReusableCellWithReuseIdentifier("myCell", forIndexPath: indexPath) as! MyCell
[...]
}
and dont forget to register your cell first
override func viewDidLoad() {
super.viewDidLoad()
//do your stuff
collectionView.delegate = self
collectionView.dataSource = self
collectionView.backgroundColor = UIColor.whiteColor()
collectionView.registerClass(MyCell.self, forCellWithReuseIdentifier: "myCell")
}
and Voila !
Create new file collection cell with XIB
In your "item at row for index" delegate method in view controller, initialize cell and return it.
Now any collection view within you view controller have the same cell
Create a Swift class(CollectionViewCell) by having UICollectionViewCell as a base class. Select create nib option while doing that.
Then create a view controller and add collection view to it in your storyboard and hook up this custom cell class in Identity Inspector. Basically, your structure needs to look like below

What's wrong with register(_:forCellWithReuseIdentifier:) on UICollectionView?

I'm working with an UICollectionView. As dequeueReusableCell(withReuseIdentifier:for:) expects You must register a class or nib file using the register(_:forCellWithReuseIdentifier:) method before calling this method, I added a line in my viewDidLoad func as
self.collectionView!.register(PhotoCollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
Now when I'm using the cell for dequeuing and configuring, I'm getting error and app crashes.
fatal error: unexpectedly found nil while unwrapping an Optional value
This is my DataSource method:
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier,
for: indexPath) as! PhotoCollectionViewCell
let aPhoto = photoForIndexPath(indexPath: indexPath)
cell.backgroundColor = UIColor.white
cell.imageView.image = aPhoto.thumbnail //this is the line causing error
return cell
}
And this is my PhotoCollectionViewCell class
class PhotoCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var imageView: UIImageView! //I double checked this IBOutlet whether it connects with Storyboard or not
}
Original question
Now comes the interesting part.
I'm using a prototype cell in the UICollectionView and I set a reusable identifier from attributes inspector. Also I changed the custom class from identity inspector to my PhotoCollectionViewCell.
I searched for the same issue and found out that when using prototype cell, deleting
self.collectionView!.register(PhotoCollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
from code will work. I gave it a try and it works.
But I'm curious to know the reason behind this issue. I couldn't reproduce the same issue with UITableView but with UICollectionView.
Not a possible duplicate:
This UICollectionView's cell registerClass in Swift is about how to register class in UICollectionView. But my question doesn't expect how to register. My question is about an issue that isn't true with UITableView class but with UICollectionView only. I'm expecting the actual difference between this conflicting issue.
There are 3 ways to register a cell (either for UITableView or UICollectionView).
You can register a class. That means the cell has no nib or storyboard. No UI will be loaded and no outlets connected, only the class initializer is called automatically.
You can register a UINib (that is, a xib file). In that case the cell UI is loaded from the xib and outlets are connected.
You can create a prototype cell in the storyboard. In that case the cell is registered automatically for that specific UITableViewController or UICollectionViewController. The cell is not accessible in any other controller.
The options cannot be combined. If you have a cell prototype in the storyboard, you don't have to register again and if you do, you will break the storyboard connection.
You can assign Nib to Collection view cell with an identifier as follows :
self.collectionView.register(UINib(nibName: "nibName", bundle: nil), forCellWithReuseIdentifier: "cell")
Hope it helps.

Add a view to CollectionView header in StoryBoard

I have 2 views on top of my CollectionView and just want to scroll on all these 3 views. I understand the best approach is to place these 2 top views in my collectionView header. How can I achieve this in storyboard (interface builder) without any code?
(I use this way in my another tableView but I have can't do this with CollectionoView)
I drag those 2 views to my collectionView's reusableView(headerView) and I've faced with this error:
enter image description here
There is no way you can drag and drop in interface builder and get header view for collection view. You have to additionally implement viewForSupplementaryElementOfKind method which returns UICollectionReusableView. While using collection reusable view, we have to treat that view in different way similar to stuffs we do for reusable cell.
Steps to follow.
Create a class (HeaderViewExample) for that header view.
Assign class (HeaderViewExample) to the reusable view you have just added in interface builder.
Give a reusable identifier (HeaderViewExample) to that reusable view.
Now you add label or buttons to the reusable view and create outlets for those outlets in the Class HeaderViewExample.
(Note: While using reusable views, don't create outlets directly in the controller.)
Now Update your CollectionViewController with the below code.
override func collectionView(collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, atIndexPath indexPath:
NSIndexPath) -> UICollectionReusableView {
var reusableView = UICollectionReusableView()
if kind == UICollectionElementKindSectionHeader {
guard let view = collectionView?.dequeueReusableSupplementaryViewOfKind(kind, withReuseIdentifier: String(HeaderViewExample), forIndexPath: indexPath) as? HeaderViewExample else { return reusableView }
view.label = "Test String"
view.backgroundColor = UIColor.redColor()
} else {
assert(false, "Unexpected element kind")
}
return reusableView
}

CollectionView in ScrollView

I am working on an iOS app where I want to show a UIScrollView with two UILabels an UIImageView and a UICollectionView at the bottom. Now I don't know how to do this in auto layout, who could help me out?
I've tried just adding everything and setting the constraints to each other, but I do remember that the UIScrollView needs to calculate the intrinsic content height. How can I create this scroll view?
I would avoid embedding the UICollectionView into a UIScrollView in this case. It will be easier to add the UILabels and UIImageView into a section header using a UICollectionReusableView subclass.
Here are the steps:
Add a section header to the UICollectionView:
Create your section header view class by subclassing UICollectionReusableView. Set custom class and reuse identifier of the header reusable view:
Lay out your header view. Connect your outlets.
Implement the viewForSupplementaryElementOfKind method.
override func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
// If you also use footers:
// use a switch statement on the 'kind' argument to
// decide which view to dequeue.
let view = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "Header", for: indexPath)
// set up your header view
return view
}

Table View Controller in storyboard with Class

I added a Table View Controller to my storyboard. Then i set the Class of the Table View Controller to my class SubscriptionsTableViewController: UITableViewController
Now i want to populate it with a cell i've made.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.dequeueReusableCellWithIdentifier("subscriptionCell") as! SubscriptionsTableViewCell
return cell
This gives me Value of type SubscriptionsTableViewController has no member dequeueReusableCellWithIdentifier
How do i access the dequeueReusableCellWithIdentifier in TableViewController class? Shouldn't i be able to use self.dequeueReusableCellWithIdentifier since i've set the class in Storyboard?
dequeueReusableCellWithIdentifier is not UITableViewController method. It is UITableView method
So, you need
let cell = tableView.dequeueReusableCellWithIdentifier("subscriptionCell") as! SubscriptionsTableViewCell
Check the documentation first.
Be sure to register SubscriptionsTableViewCell as cell class of your table view.

Resources