Interface Builderで@IBOutlet to CustomView
として宣言されているViewController
のデリゲートプロパティに接続できません。単に接続を確立できません。
これがコードです
class CustomView: UIView {
@IBOutlet var delegate: CustomViewDelegate?
}
@objc protocol CustomViewDelegate {
...
}
class ViewController: UIViewController, CustomViewDelegate {
...
}
@objc
は Swiftプロトコルのために使用されます。IBOutletプロパティは非オブジェクトタイプにすることはできません 。理由はわかりませんprotocol CustomViewDelegate: class {}
は機能しません。
他の誰かがそのようなものに出くわしましたか?
Xcodeリリースノートから:
インターフェイスビルダーは、Swiftファイル内のコンセントへの接続をサポートしません(コンセントのタイプがプロトコルの場合)。
回避策:アウトレットのタイプをAnyObjectまたはNSObjectとして宣言し、Interface Builderを使用してオブジェクトをアウトレットに接続してから、アウトレットのタイプをプロトコルに戻します。
編集: Xcode 9ベータ3のリリースノートには、この回避策は不要になると記載されています。
Adam Waiteは素晴らしい回避策を提供します。 ただし、回避策を強調し、Xcodeが修正されたら余分なプロパティも簡単に削除できるため、次の解決策を好みます。
class CustomView: UIView {
@IBOutlet
public var delegate: CustomViewDelegate?
/// Workaround for Xcode bug that prevents you from connecting the delegate in the storyboard.
/// Remove this extra property once Xcode gets fixed.
@IBOutlet
public var ibDelegate: AnyObject? {
get { return delegate }
set { delegate = newValue as? CustomViewDelegate }
}
func someMethod() {
// Here we always refer to `delegate`, not `ibDelegate`
delegate?.onSomethingHappened()
}
}
@objc protocol CustomViewDelegate {
...
}
ねえ、このバグはもう1年半前のものですか?
エレガントな回避策:
#if TARGET_INTERFACE_BUILDER
@IBOutlet open weak var delegate: AnyObject?
#else
open weak var delegate: CustomViewDelegate?
#endif
参照: https://github.com/WenchaoD/FSPagerView/blob/master/Sources/FSPagerView.Swift#L88
美しくない別の:
@IBOutlet weak var ibDelegate: NSObject?
@IBOutlet weak var ibDataSource: NSObject?
var delegate: MultipleButtonViewDelegate? { return ibDelegate as? MultipleButtonViewDelegate }
var dataSource: MultipleButtonViewDataSource? { return ibDataSource as? MultipleButtonViewDataSource }
これは古いスレッドですが、Xcode 9ベータ3以降、Swiftで記述されたカスタムデリゲートをインターフェイスビルダーに接続できるようになりました。
リリースノートによると
Interface Builderは、Swiftプロトコル拡張機能を持つクラスで宣言されたアウトレット、アクション、および検査可能なプロパティを認識します。(22201035)
// Can connect this to interface builder now
class MyViewController: UIViewController {
@IBOutlet weak var myDelegate: TheNewDelegate?
}
私にとっての理由は、テーブルビューがデータソースとデリゲートを設定しようとした時点でのテーブルビューがnil
だったからです。これは、指定されたイニシャライザがinitWithNibName:bundle:
を呼び出して 初期化された接続 を保証しないためでした。デリゲートとデータソースの設定をviewDidload
に延期することは、魅力的なように機能しました。