progrium / darwinkit

Native Mac APIs for Go. Previously known as MacDriver
MIT License
4.42k stars 147 forks source link

Higher level subclassing API #207

Closed progrium closed 10 months ago

progrium commented 10 months ago

This PR introduces objc.NewClass[T](), which takes a struct type implementing IObject that it uses to allocate a class. It uses reflection to set the class name from the struct type name, and uses NSObject as the super unless specified by a struct tag. It optionally takes selectors that will be added as methods using the struct methods with Go equivalent name. The resulting class can be registered and has a type specific New() that initializes and autoreleases.

Example

type CustomView struct {
    appkit.View `objc:"NSView"`
}

func (v CustomView) AcceptsFirstResponder() bool {
    return true
}

func (v CustomView) KeyDown(event appkit.Event) {
    log.Println("Keydown:", v.Class().Name(), event.Class().Name())
}

func main() {
    // passing a selector that doesn't have a matching Go method will panic
    CustomViewClass := objc.NewClass[CustomView](
        objc.Sel("acceptsFirstResponder"),
        objc.Sel("keyDown:"),
    )
    objc.RegisterClass(CustomViewClass)

    // New() returns a CustomView, but InitWithFrame() will return a View.
    // If you need CustomView, you can assign it before the View init method.
    view := CustomViewClass.New().InitWithFrame(rectOf(0, 0, 150, 99))

    ...
}

More examples can be found in the tests or the updated subclass example.

Breaking Changes

Changes the Class() method on objc.Class and objc.IClass to MetaClass().