web-dev-qa-db-ja.com

Swift

Interface Builderで@IBOutlet to CustomViewとして宣言されているViewControllerのデリゲートプロパティに接続できません。単に接続を確立できません。

これがコードです

class CustomView: UIView {
     @IBOutlet var delegate: CustomViewDelegate?
}

@objc protocol CustomViewDelegate {
     ...
}


class ViewController: UIViewController, CustomViewDelegate {
     ...
}

@objcSwiftプロトコルのために使用されます。IBOutletプロパティは非オブジェクトタイプにすることはできません 。理由はわかりませんprotocol CustomViewDelegate: class {}は機能しません。

他の誰かがそのようなものに出くわしましたか?

28
Dmitry

Xcodeリリースノートから:

インターフェイスビルダーは、Swiftファイル内のコンセントへの接続をサポートしません(コンセントのタイプがプロトコルの場合)。

回避策:アウトレットのタイプをAnyObjectまたはNSObjectとして宣言し、Interface Builderを使用してオブジェクトをアウトレットに接続してから、アウトレットのタイプをプロトコルに戻します。

編集: Xcode 9ベータ3のリリースノートには、この回避策は不要になると記載されています。

58
matt

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年半前のものですか?

16
Lars Blumberg

エレガントな回避策:

#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

9
WenchaoD

美しくない別の:

@IBOutlet weak var ibDelegate: NSObject?
@IBOutlet weak var ibDataSource: NSObject?
var delegate: MultipleButtonViewDelegate? { return ibDelegate as? MultipleButtonViewDelegate }
var dataSource: MultipleButtonViewDataSource? { return ibDataSource as? MultipleButtonViewDataSource }
8
Adam Waite

これは古いスレッドですが、Xcode 9ベータ3以降、Swiftで記述されたカスタムデリゲートをインターフェイスビルダーに接続できるようになりました。

リリースノートによると

Interface Builderは、Swiftプロトコル拡張機能を持つクラスで宣言されたアウトレット、アクション、および検査可能なプロパティを認識します。(22201035)

// Can connect this to interface builder now    
class MyViewController: UIViewController {
    @IBOutlet weak var myDelegate: TheNewDelegate?
}
3
DerrickHo328

私にとっての理由は、テーブルビューがデータソースとデリゲートを設定しようとした時点でのテーブルビューがnilだったからです。これは、指定されたイニシャライザがinitWithNibName:bundle:を呼び出して 初期化された接続 を保証しないためでした。デリゲートとデータソースの設定をviewDidloadに延期することは、魅力的なように機能しました。

1
Tom Howard