Skip to content

Move instance variables back into define_class! #788

@madsmtm

Description

@madsmtm

In #521, I changed instance variables to require a separate type that stores all the instance variables. There were a bunch of reasons for that, but the primary one is that you have to be able to name it when using PartialInit::set_ivars.

E.g. you might imagine a different design where:

define_class!(
    #[unsafe(super(NSObject))]
    struct Point {
        x: f32,
        pub y: f32,
    }
);

// Generates:
impl Point {
    fn x(&self) -> f32 { ... }

    pub fn y(&self) -> f32 { ... }
}

This would work now that we have removed mutability (so we wouldn't need a way to also create Point::set_x(&self)), but it'd be impossible to safely construct this, since we wouldn't have a way to write:

impl Point {
    fn new(x: f32, y: f32) -> Retained<Self> {
        let this = Self::alloc();

        // What do we write here? We don't have an `Ivars` struct any more!
        // Maybe a builder like `this.x(x).y(y).ivars_set()`? But that'd probably be hard.
        let this = this.set_ivars(...);

        unsafe { msg_send![super(this), init] }
    }
}

I thought we couldn't make define_class! create this type for us, since the user would have no way to name it, but with a type-alias like the following, they actually could!

pub type Ivars<T> = <T as DefinedClass>::Ivars;

This even allows you to construct an instance of the struct, see this playground.

// Usage
let this = this.set_ivars(Ivars::<Point> {
    x: 1.0,
    y: 2.0,
});

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-objc2Affects the `objc2`, `objc2-exception-helper` and/or `objc2-encode` cratesenhancementNew feature or request

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions