2014-07-03 12 views
14

Ich möchte eine benutzerdefinierte swift Delegate in IB verdrahten. Der Delegat ist ein Objekt, das ein bestimmtes Protokoll in swift implementiert.Swift-Protokoll, IBOutlet-Eigenschaft kann nicht Nicht-Objekt-Typ haben

protocol ThumbnailTableViewCellDelegate { 
    func cellWasTouched(thumbnail: Bool, cell: UITableViewCell) 
} 

class ThumbnailTableViewCell: UITableViewCell { 
    @IBOutlet var thumbnailTableViewCellDelegate: ThumbnailTableViewCellDelegate? 
} 

leider beschwert sich der Compiler mit:

error: 'IBOutlet' property cannot have non-object type 'ThumbnailTableViewCellDelegate' 
    @IBOutlet var thumbnailTableViewCellDelegate: ThumbnailTableViewCellDelegate? 
    ^~~~~~~~~ 
+3

@Andy Es ist vollkommen in Ordnung - Sie sagen, es ist ein Objekt, das diesem Protokoll entspricht. –

Antwort

27

Sie haben Ihre ThumbnailTableViewCellDelegate Protokoll zu erklären, wie @objc:

@objc protocol ThumbnailTableViewCellDelegate { 
    func cellWasTouched(thumbnail: Bool, cell: UITableViewCell) 
} 

Dies liegt daran, @IBOutlet die Variable als weak erklärt, die nur Arbeitet mit Objekten. Ich bin nicht sicher, warum Sie nicht einfach sagen können, das Protokoll entspricht AnyObject, vielleicht ist das ein Swift-Bug.

+0

Danke Nate, das hat funktioniert!Ist dies eine temporäre Problemumgehung oder erwartetes Verhalten? Welche Relevanz hat @objc in diesem Fall? – pixbroker

+1

Diese Methode funktioniert nicht mehr für mich (mit dem GM-Seed von Xcode 6.) – Ash

+9

Dies kompiliert, aber ich habe Probleme beim Verbinden der Steckdose im Storyboard jetzt –

-1

IBOutlets sollen einen Zeiger auf ein Objekt anzeigen, das in einer NIB- (oder Storyboard-) Datei gespeichert ist. Ein Protokoll ist kein Objekt, daher können Sie keines in einer NIB-Datei haben. Mache den Typ der IBOutlet-Variable zum Typ des tatsächlichen Objekts, das du in der Spitze hast.

0

Eine Variable des Protokolltyps ist möglicherweise kein Objekt, da structs und enums auch Protokollen entsprechen können. Um sicherzustellen, dass ein Protokoll nur an Klassen angepasst werden kann, können Sie das Protokoll mit @class_protocol deklarieren.

0

Nicht ideal, aber eine Option ist, so etwas zu tun:

@IBOutlet var objectType: NSObject! 

private var conformingObject: SomeProtocol { 
    return objectType as SomeProtocol 
} 

Got um sicherzustellen, dass Ihre objectType zu SomeProtocol oder Dinge entspricht explodiert

14

Sie können Ihre eigenen Protokolle in IB in Verbindung mit dieser Problemumgehung. Es ist ein bekanntes Problem mit Xcode und wird wahrscheinlich eines Tages gelöst werden. Bis dahin:

  1. Deklarieren Sie den Delegaten als AnyObject - @IBOutlet var-Delegat: AnyObject!
  2. Verbinden Sie den Delegaten in Interface Builder
  3. Ändern Sie den Typ der Steckdose zu Ihrem Protokoll, z. @IBOutlet var delegieren: MyDelegate

Das funktioniert für mich.

+0

Gibt es einen bekannten Radar- oder Release-Hinweis, wo dies dokumentiert ist? –

0

Es macht Sinn, dass IB AnyObject erfordert, und nicht Ihr spezielles Protokoll. Das Objekt, das Sie wollen wahrscheinlich verbinden, aber nicht entspricht notwendigerweise auf das Protokoll und das Protokoll kann optionals haben - so:

Sie Ihr Protokoll wie folgt aus:

@objc public protocol HexViewDataSource: NSObjectProtocol { 
    @objc optional func dataAtOffset (_ hexView: HexView, offset: UInt64, length: Int)-> Data? 
    @objc optional func dataLength (_ hexView: HexView) -> UInt64 
} 

erklären es in Ihrer Klasse wie folgt zum Beispiel:

@IBOutlet weak open var dataSource: AnyObject? 

und wenn Sie kommen, es zu benutzen, überprüfen Sie, dass es dem Protokoll entspricht, und dass die optionals existieren - wie folgt aus:

if let dataSource = dataSource as? HexViewDataSource, let dfr = dataSource.dataAtOffset { 
    setRowData(offset: offset, data: dfr (self, offset, bytesPerRow)) 
} 
Verwandte Themen