49

I have created a small sample project using Swift. I have created an "MyCustomView" as xib which contains label, button and imageView as shown in below code:

import UIKit

@IBDesignable class MyCustomView: UIView {

    @IBOutlet weak var lblName: UILabel!
    @IBOutlet weak var btnClick: UIButton!
    @IBOutlet weak var myImageView: UIImageView!

    var view:UIView!

    @IBInspectable
    var mytitleLabelText: String? {
        get {
            return lblName.text
        }
        set(mytitleLabelText) {
            lblName.text = mytitleLabelText
        }
    }

    @IBInspectable
    var myCustomImage:UIImage? {
        get {
            return myImageView.image
        }
        set(myCustomImage) {
            myImageView.image = myCustomImage
        }
    }


    override init(frame : CGRect)
    {
        super.init(frame: frame)
        xibSetup()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        xibSetup()
    }


    func xibSetup()
    {
        view = loadViewFromNib()
        view.frame = self.bounds

        // not sure about this ?
        view.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight]
        addSubview(view)
    }


    func loadViewFromNib() -> UIView {

        let bundle = NSBundle(forClass: self.dynamicType)
        let nib = UINib(nibName: "MyCustomView", bundle: bundle)
        let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView

        return view
    }
}

Attached the image of xib for the reference. Screenshot

In StoryBoard -> ViewController added UIViewCollection which as shown in the below image. In this viewcollection, I need that orange color cell to contain my custom xib to be loaded at runtime.

How do I achieve this?

enter image description here

New Modified code as suggested by Sandeep

// 1 import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var collectionView: UICollectionView!

    override func viewDidLoad() {
        super.viewDidLoad()

        self.collectionView.register(UINib(nibName: "MyCustomView", bundle: nil), forCellWithReuseIdentifier: "myCell")

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 7
    }

    func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
        return 1
    }

    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

        let cell : MyCustomView = collectionView.dequeueReusableCellWithReuseIdentifier("your_reusable_identifier", forIndexPath: indexPath) as! MyCustomView

        cell.lblName.text = "MyNewName"
        return cell
    }
}

// 2 import UIKit

@IBDesignable class MyCustomView: UICollectionViewCell {

    @IBOutlet weak var lblName: UILabel!
    @IBOutlet weak var btnClick: UIButton!
    @IBOutlet weak var myImageView: UIImageView!

    var view:UIView!

    @IBInspectable
    var mytitleLabelText: String? {
        get {
            return lblName.text
        }
        set(mytitleLabelText) {
            lblName.text = mytitleLabelText
        }
    }

    @IBInspectable
    var myCustomImage:UIImage? {
        get {
            return myImageView.image
        }
        set(myCustomImage) {
            myImageView.image = myCustomImage
        }
    }

}
1
  • Please change let cell : MyCustomView = collectionView.dequeueReusableCellWithReuseIdentifier("your_reusable_identifier", forIndexPath: indexPath) as! MyCustomView to let cell : MyCustomView = collectionView.dequeueReusableCellWithReuseIdentifier("myCell", forIndexPath: indexPath) as! MyCustomView Commented May 19, 2016 at 8:42

4 Answers 4

114

Here is what you can do,

  1. Change your MyCustomView class to be a subclass of UICollectionViewCell and not UIView.

  2. Remove override init(frame : CGRect),required init?(coder aDecoder: NSCoder),func xibSetup(),func loadViewFromNib() -> UIView from MyCustomView

  3. 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.

  4. Finally you will be left with just IBOutlets in MyCustomView.

  5. For better coding practice change the name from MyCustomView to MyCustomCell (optional)

  6. Go to your xib, select the xib and set its class as MyCustomView.

enter image description here

  1. In the same screen change file owner to yourView controller hosting collectionView

enter image description here

  1. In ViewDidLoad of your viewController register your nib.
self.collectionView.registerNib(UINib(nibName: "your_xib_name", bundle: nil), forCellWithReuseIdentifier: "your_reusable_identifier")
  1. 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
  1. 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.

Sign up to request clarification or add additional context in comments.

9 Comments

@yannis-p : Sorry saw your message now, wasn't really active on SO for quite sometime, I hope you got your answer by now, but if not, if you would like to use same xib/cell accross multiple ViewControllers you can skip step 7 :) Thats all follow other steps as is n there shouldn't be any issue :)
I actually just ended up making the cell/presentation customizable, but I'm reusing the same logic for many different screen just with different content which is better. But thanks your answer will be useful in the future when I decided to reuse UI :)
Your step-by-step worked perfectly. Thanks! (iOS 13 / Swift 5)
registerNib has been renamed to register. Small update to Step #8 ;)
|
19

For Swift 4.0

in viewDidLoad:

//custom collectionViewCell
mainCollectionView.register(UINib(nibName: "your_customcell_name", bundle: nil), forCellWithReuseIdentifier: "your_customcell_identifier")

in cellForItemAt indexPath:

let cell : <your_customcell_name> = mainCollectionView.dequeueReusableCell(withReuseIdentifier: "your_customcell_identifier", for: indexPath) as! <your_customcell_name>

And dont forget to set identifier for your custom cell in xib section.

Comments

5

One line approach if you have to register multiple cells.

extension UICollectionViewCell {

    static func register(for collectionView: UICollectionView)  {
        let cellName = String(describing: self)
        let cellIdentifier = cellName + "Identifier"
        let cellNib = UINib(nibName: String(describing: self), bundle: nil)
        collectionView.register(cellNib, forCellWithReuseIdentifier: cellIdentifier)
    }
}

Steps on how to use

  1. Name your Cell identifier as "YourcellName" + "Identifier" eg: CustomCellIdentifier if your cell name is CustomCell.

  2. CustomCell.register(for: collectionView)

Comments

0

For Swift 4.2 in viewDidLoad

 self.collectionView.register(UINib(nibName: "your_xib_name", bundle: nil), forCellWithReuseIdentifier: "your_reusable_identifier")

in cellForItemAt indexPath:

let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "your_reusable_identifier", for: indexPath) as! MyCustomView

And of course as @Raj Aryan said: don't forget to set identifier for your custom cell in xib section.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.