SwiftのOptional型をViewControllerでどう使っていくかについて書きまとめたいと思います。Optional型およびOptional Chainingについての基本的なことは以下にまとめたので参考にしてください。

Optional Chaining | Swiftの基本的な使い方

viewDidLoadで初期化するものはOptional!型を使う

var names: [String]

このようにプロパティを宣言すると、initメソッドで初期化しないとコンパイルエラーになります。ViewControllerの場合、viewDidLoadで初期化したい場合も多いでしょう。

その場合、Optional!型で宣言するとよいでしょう。

var names: [String]!

viewDidLoadで初期化し、以降は!や?をつけることなくメソッド呼び出しができます。もしnilでないならランタイムエラーでクラッシュします。

InterfaceBuilderで配置したSubviewはIBOutletで宣言しますが、これらは以下のようにweakのOptional!型で宣言するとよいでしょう。

@IBOutlet weak var tableView: UITableView!

delegateはOptional?型を使う

delegateはviewDidLoadなどクラス内部ではなく外部から設定されるもので、nilの場合もあります。こういうものはOptional?型で宣言するべきでしょう。

weak var delegate: MyClassDelegate?

delegateメソッドを呼び出す時は以下のようにします。nilであれば何もせずランタイムエラーにもなりません。

delegate?.method1()

delegateメソッドが値を返す場合は、条件分岐したいでしょうからこう書きます。

if let count = delegate?.calculateTotalCount() {
  // delegateがnilでなく、かつ、calculateTotalCountがnil以外を返す場合、ここにくる
}

delegateメソッドがoptionalの場合、delegateはnilではないが、そのメソッドが実装されていないことがあります。その場合の呼び出しは、このようにします。

// delegateがnilでなく、かつ、optionalMethodが実装されている時は、optionalMethodが呼び出される。
delegate?.optionalMethod?()

// 戻り値を扱いたい場合
if let count = delegate?.optionalMethod?() {
  // countを使って何かする
}

Objective-C時代のようにrespondsToSelectorは使いません。

実行はしたくなくメソッドがあるかどうかの判定をしたい場合は、このようにします。

if delegate?.optionalMethod != nil {
   // optionalMethodが実装されている時のみ処理
}