Using CollectionView in UIView with xib file
The main way to use UICollectionView is by managing the logic programmatically.
First, create a new class which inherits from
UICollectionViewCell
. Choose if you want to include a xib to easily design your cell:Design your cell with Interface Builder or programmatically.
Create your main view controller including a xib (or a storyboard) with the collection view inside and link it to the associated class via Interface Builder. Alternatively you can add a collection view programmatically to your
UIViewController
Make the target view controller conform to the
UICollectionViewDelegate
andUICollectionViewDataSource
protocols by declaring them after the father class:class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
@IBOutlet weak var collectionView: UICollectionView!
//...
}Register the associated nib or the class for your cell in the
viewDidLoad
method and associate the datasource and delegate protocols to the view controller class:let cellIdentifier = "cellIdentifier"
override func viewDidLoad() {
super.viewDidLoad()
//if you use xibs:
self.collectionView.register(UINib(nibName:"MyCollectionCell", bundle: nil), forCellWithReuseIdentifier: cellIdentifier)
//or if you use class:
self.collectionView.register(MyCollectionCell.self, forCellWithReuseIdentifier: cellIdentifier)
self.collectionView.delegate = self
self.collectionView.dataSource = self
}Implement the methods declared in the
UICollectionViewDelegate
andUICollectionViewDataSource
protocols :let objects = ["Cat", "Dog", "Fish"]
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.objects.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as! MyCollectionCell
//in this example I added a label named "title" into the MyCollectionCell class
cell.title.text = self.objects[indexPath.item]
return cell
}Run your app in the simulator (or on a real device) and.. Et voilà! :)
For more info: https://developer.apple.com/reference/uikit/uicollectionview
Can´t add items to UICollectionView inside UIView xib
You can't have UICollectionViewCell when the UICollectionView is on a Nib. What you need to do is to create the UICollectionViewCell as another nib and get it registered in the class that you are using for your CollectionView.
Create a new nib, drag a UICollectionViewCell inside it, and do something like this in the class that works with your UICollectionView.
override func awakeFromNib() {
let nibName = UINib(nibName: "ClassCollectionCell", bundle:nil)
collectionView.registerNib(nibName, forCellWithReuseIdentifier: "collectionCell")
}
Remember you can add a custom class to the UICollectionViewCell so you can pass dynamic data to it.
iOS Swift - CollectionView INSIDE UIView XIB INSIDE UIViewController
Figured it out. Yes, if you want to use a CollectionView inside a XIB, and you have a custom CollectionViewCell, you have to create a XIB for the CollectionViewCell. You cannot just have a CollectionViewCell without a XIB in this case. Then, in the ViewController that contains the XIB, you have to use:
xibView.collectionView.register(UINib(nibName: "CustomCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "CustomCollectionViewCell")
Most tutorials say to do this in viewDidLoad, however I'm creating not just one XIB in the ViewController, but a bunch of them based on data pulled from a database. So I do this within the loop that builds each XIB. I was worried this wouldn't work, but it does.
The reason why you have to do this continues to elude me.
Reusing XIB views for collectionviews as a partial for other views?
(a) I have a swift file which I created; it a custom subclassed UICollectionViewCell. It has a XIB file.
Register the nib with the collection view. In cellForItemAt
, when you need a cell, dequeue it. You will receive a copy of the collection view cell from the nib. Configure it as desired. Return it.
(b) I want to reuse the same XIB elsewhere in the app, including all outlets and connections
Load the nib and pull out the first (and only) top-level view. You will receive a copy of the collection view cell from the nib. Add it as a subview to a view in the interface.
(The easiest way to do that is through UINib and its instantiate
method. This returns an array of the top-level objects.)
True, one does not usually use a collection view cell as a subview of an ordinary view. But I cannot think of any reason against it; after all, a view is a view is a view.
(If you would prefer not to do that, I can think of workarounds; for example, make the view in the nib a custom UIView and configure each cell by loading the nib and putting that view inside the cell. This will introduce some inconveniences, but it will make the nib more universally usable.)
I made a quick example. Here's the nib, very simple because it's only an example:
Here's my app, showing a collection view (showing four cells on a blue background) and also the view from the nib extracted and stuck into the interface:
Here's the entire code:
class MyView : UIView {
@IBOutlet var iv : UIImageView?
}
class MyCell : UICollectionViewCell {
var v : MyView?
}
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
@IBOutlet weak var cv: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
self.cv.register(MyCell.self, forCellWithReuseIdentifier: "cell")
let arr = UINib(nibName: "View", bundle: nil).instantiate(withOwner: nil, options: nil)
let v = arr[0] as! UIView
self.view.addSubview(v)
v.frame.origin = CGPoint(x:20, y:300)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 4
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! MyCell
if cell.v == nil {
let arr = UINib(nibName: "View", bundle: nil).instantiate(withOwner: nil, options: nil)
let v = arr[0] as! MyView
cell.contentView.addSubview(v)
cell.v = v
}
print(cell.v?.iv) // image view
return cell
}
}
Note the use of subclasses and outlets. cell.v
takes us to the view, so cell.v?.iv
takes us to the image view — and now we could perform further configuration, as desired. Thus we have one level of indirection added in order to reach a subview from the nib, but this seems a very small price to pay.
How to load custom cell ( xib) in UICollectionView cell using swift
Here is what you can do,
Change your
MyCustomView
class to be a subclass of UICollectionViewCell and not UIView.Remove
override init(frame : CGRect)
,required init?(coder aDecoder: NSCoder)
,func xibSetup()
,func loadViewFromNib() -> UIView
fromMyCustomView
I seriously could not understand how are you using your setter and getter for mytitleLabelText and myCustomImage. If its of no use get rid of it as well.
Finally you will be left with just IBOutlets in MyCustomView.
For better coding practice change the name from MyCustomView to MyCustomCell (optional)
Go to your xib, select the xib and set its class as MyCustomView.
- In the same screen change file owner to yourView controller hosting collectionView
- In ViewDidLoad of your viewController register your nib.
self.collectionView.registerNib(UINib(nibName: "your_xib_name", bundle: nil), forCellWithReuseIdentifier: "your_reusable_identifier")
- In cellForItemAtIndexPath,
let cell : MyCustomView = collectionView.dequeueReusableCellWithReuseIdentifier("your_reusable_identifier", forIndexPath: indexPath) as! MyCustomView
cell.lblName.text = "bla bla" //access your Cell's IBOutlets
return cell
- Finally in order to control the size of cell either override the delegate of collectionView or simply go to your collectionView select the collectionCell in it and drag it to match your dimension :) Thats it :)
Happy coding. Search tutorials for better understanding. I can't explain all delegates as I'll end up writing a blog here.
Happy coding
UICollectionView inside UIView Nib
In case of adding a collection view/ table view in a UIView with separated .xib file, you should also create a separated .xib custom cell.
In your UIView Custom class, you should implement register(_:forCellWithReuseIdentifier:), for example:
// collectionView is the IBOutlet for the collection view that exists in the view .xib file
collectionView.register(UINib(nibName: "CustomCollectionViewCell", bundle: nil), forCellReuseIdentifier: "CustomCollectionViewCell")
And you will be good to go.
How to create outlet from collection cell xib file to collection view controller
You can't do that.
You can't create an outlet that references a UITextField placed inside a custom CollectionViewCell in your CollectionViewController.
What you can do is create an outlet that references the UITextField in your .xib in the respective CollectionViewCell .swift class (1), create an outlet that references your collectionView in the CollectionViewController (2), and use these CollectionViewCells in your collectionView (3).
You can then access the UITextField of a specific CollectionViewCell in your CollectionViewController through the cell itself (3), like for instance with:
let indexPath = IndexPath(row: 2, section: 0)
let cell = self.collectionView.cellForItemAtIndexPath(indexPath) as! CollectionViewCell // so the compiler knows that the cell you are referring to is of type CollectionViewCell and thus has your custom textField property
let textInTextField = cell.textField.text
(1)
(2)
(3)
Strange UIView in a UICollectionViewCell created from nib
It's the contentView
of the cell – see the documentation.
Your subviews should be added to the contentView
rather than the cell directly, where they are currently. This has happened because your nib is a plain UIView
which doesn't contain the contentView
property.
What you need to do is design your nib with a UICollectionViewCell
object, by simply dragging the appropriate object into the interface builder:
Related Topics
Can't Find Pods.Modulemap - Looking in Wrong Directory
Why My App Is Not Shown in Icloud Drive Folder
Use Uibarbuttonitem Icon in Uibutton
Showing a Uipickerview with Uiactionsheet in iOS8 Not Working
Detect When a Webview Video Becomes Fullscreen on iOS8
Swiftui Datepicker Jumps Between Short and Medium Date Formats When Changing the Date
Accessorybuttontappedforrowwithindexpath: Not Getting Called
How to Tell If Your Code Is Running on an iPhone or an Iphone3G
Nsurlconnection Deprecated in iOS9
Detect If Swift App Is Being Run from Xcode
Avaudioplayer Produces Lag Despite Preparetoplay() in Swift
How to Create and Send the JSON Data to Server Using Swift Language
How to Get the Build Uuid in Runtime and the Image Base Address
Can Siri Be Invoked Programmatically Within My App Using Private APIs