progrium/darwinkit

ComboBox `SetDelegate` uses `TextField`'s `SetDelegte` resulting in error

corruptmemory opened this issue · 1 comments

Example:

items := []objc.IObject{
    foundation.NewStringWithString("a"),
    foundation.NewStringWithString("b"),
}

cb := appkit.NewComboBox()
cb.AddItemsWithObjectValues(items)

cbd := &appkit.ComboBoxDelegate{}
cb.SetDelegate(cbd)

Will fail at run time because the particular SetDelegate method invoked is this one:

func (t_ TextField) SetDelegate(value PTextFieldDelegate) {
	po0 := objc.WrapAsProtocol("NSTextFieldDelegate", value)
	objc.SetAssociatedObject(t_, objc.AssociationKey("setDelegate"), po0, objc.ASSOCIATION_RETAIN)
	objc.Call[objc.Void](t_, objc.Sel("setDelegate:"), po0)
}

And since we are giving it a ComboBoxDelegate instead of a TextFieldDelegate, the reflective type check fails.

I've built a work-around for this:

func setComboBoxDelegate(cb appkit.ComboBox, value appkit.PComboBoxDelegate) {
	po0 := objc.WrapAsProtocol("NSComboBoxDelegate", value)
	objc.SetAssociatedObject(cb, objc.AssociationKey("setDelegate"), po0, objc.ASSOCIATION_RETAIN)
	objc.Call[objc.Void](cb, objc.Sel("setDelegate:"), po0)
}

But needless to say, the current behavior isn't what a user would expect.

It is possible that generation would make a SetDelegate for ComboBox and skips it because it already exists in TextField, so that would be a generation bug. And your workaround is fine, but there is also always a generic Object version of any method that takes a Protocol interface, in this case SetDelegateObject.