Xib and Storyboard

Purpose

An Xib view allows you to create a single view that can be used in several places in the app. All modifications are made on a single view. An associated UIView file makes the view controller lighter, by hosting all the outlets.

Capture d’écran 2021-08-20 à 18.12.54.png

XIB / NIB

Xib = Xcode Interface Builder

Nib = Nextstep Interface Builder

Create an Xib Custom View and storyboard

  • Create a Xib file (New File/View)

GridView.xib

When you open this new file, you can create a custom view in Interface Builder.

You can choose the freedom shape in the attributes inspector. This will let you click on the view and change the shape as you see.

  • Create a custom UIView file (New File/Cocoa Touch/UIView)

Give it the same name as the associated xib view

GridView.swift

  • Connect XIB file and custom UIView

Click back into the Xib file. In the File's Owner placholders, enter the name of the UIView file as Class, in the Identity inspector.

GridView

  • UIView Initializers

As a UIView can be created in the interface builder (storyboard, Xib) or programmatically in code, there is an initialiser for each.

In GridView.swiftfile, add these two classic initializers, and a function to load the xib.

        class GridView: UIView {
            override init(frame: CGRect) {
                super.init(frame: frame)
                loaderNib()
            }

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

             private func loaderNib() {
                Bundle.main.loadNibNamed("GridView", owner: self, options: nil)
                addSubview(contentView)
                contentView.frame = self.bounds
                contentView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
            }
        }
`

The first line will search for the loaded xib by name. Then the view is added with the ability to adapt to the dimensions of the container view that will display it in the storyboard.

There are other methods you may prefer. The choice is yours.

  • Link the Xib custom view and its objects to the UIView file

Create an outlet for the Xib view

@IBOutlet var contentView: UIView!

Then one for each object and action (@IBAction)

@IBOutlet weak var gridButtons: [UIButton]!

@IBAction func chooseImage(_ sender: UIButton) { }

  • Using this custom view in the storyboard

    In the storyboard, add a UIView that will contain the xib view. Link this view with an outlet to the view controller.

         class ViewController: UIViewController {
    
             @IBOutlet weak var gridView: GridView!
    
             override func viewDidLoad(){
             ...
         }
    

The type of this view is the custom view of the xib.

You have access to the properties and methods defined in the GridView.swift

gridView.gridButtons[1].setBackgroundImage(currentImage, for: .normal)

UIButton Action

One way to manage the action of a button is to create a property

var currentButton: (() -> Void)? = nil

And to implement the IBAction as follows :


@IBAction func chooseImage(_ sender: UIButton) {

     if let currentButton = self.currentButton {
        currentButton()
    }
}

In the controller, you can get the action and implement it. For example to call an image picker.

      private func selectImage() {
            gridView.currentButton = {
                self.imagePicker.allowsEditing = true
                self.imagePicker.sourceType = .photoLibrary
                self.present(self.imagePicker, animated: true)
            }
        }

the final word

The size of the xib view does not matter, as it will fit the container view of the storyboard(or code)

Have fun with code