Swift closures are powerful. If the block is not executed in the current method, it is logged with a property that can be called as needed.

Define closure properties:

EmoticonView.swift

/// select the emoticon callback

    private var selectedEmoticonCallBack: (_ emoticon: Emoticon) - > ()Copy the code

If the closure is not set to optional, you need to customize the constructor to create the closure properties:

Record the closure properties before setting them up

EmoticonView.swift

// MARK: - constructor

    init(selectedEmoticon: @escaping (_ emoticon: Emoticon) - > ()) {

        // Record closure properties

        selectedEmoticonCallBack = selectedEmoticon

        

        // Call the parent constructor

        var rect = UIScreen.main.bounds

        rect.size.height = 226

        

        super.init(frame: rect)

        

        backgroundColor = UIColor.white

        

        setupUI()

        

        // Scroll to page 1

        let indexPath = NSIndexPath(item: 0, section: 1)

        

        DispatchQueue.main.async {

            self.collectionView.scrollToItem(at: indexPath as IndexPath, at: .left, animated: false)}}Copy the code

Set the closure contents

ViewController.swift

/// emoticons keyboard view

    private lazy var emoticonView: EmoticonView = EmoticonView{[weak self] (emoticon) -> () in

        // Close the closure with self

        self?.insertEmoticon(em: emoticon)

// self? .textView.text = emoticon.chs

    }
    
    /// Insert emoticons

    ///

    /// -parameter em

    func insertEmoticon(em: Emoticon) {

        textView.text = em.chs

    }
Copy the code

Pass the argument and execute the callback:

EmoticonView.swift

//MARK: - proxy method

    func collectionView(_ collectionView: UICollectionView.didSelectItemAt indexPath: IndexPath) {

// print(indexPath)

        // Get the expression model

        let em = packages[indexPath.section].emoticons[indexPath.item]

        

        // Perform 'callback'

        selectedEmoticonCallBack(em)

    }
Copy the code

Circular reference problem

(self) The controller strongly references the emoticonView—- the emoticonView defines closure properties —–VC strongly references the closure

The closure strongly references self

[weak self] [weak self]

class ViewController: UIViewController {

/// emoticons keyboard view

    private lazy var emoticonView: EmoticonView = EmoticonView{[weak self] (emoticon) -> () in

        // Close the closure with self

        self?.insertEmoticon(em: emoticon)

// self? .textView.text = emoticon.chs

    }
    
    .}
Copy the code

Test loop reference problem:

Write to current controller:

deinit {

        print("888")}Copy the code

Test by adding navigationController before the current controller