Skip to content

Better autorelease ergonomics #86

Closed
@madsmtm

Description

@madsmtm

The ergonomics of using autoreleased references are not great, especially when you are creating your own class. We should try to do better!

I see mainly three use-cases (for library / binding creators; end users probably won't touch this part of the library):

  1. Returning a reference (shared in the example, could also be mutable)
    pub fn description<'pool>(&self, pool: &'pool AutoreleasePool) -> &'pool NSString {
        let desc: *const NSString = msg_send![self, description];
        pool.ptr_as_ref(desc)
    }
  2. Exposing a retained version of the above:
    pub fn description_retained<'pool>(&self, pool: &'pool AutoreleasePool) -> Id<NSString, Shared> {
        // SAFETY: The NSString is valid and not mutably owned anywhere
        // The unsafe is required because the `&NSString` could have come from an `Id<NSString, Owned>`.
        unsafe { Id::retain(self.description(pool)) }
    }
    // Or
    pub fn description_retained(&self) -> Id<NSString, Shared> {
        autoreleasepool(|pool| {
            unsafe { Id::retain(self.description(pool)) }
        })
    }
  3. Returning an autoreleased object in a custom / overridden method:
    extern "C" valid_attributes(_this: &Object, _sel: Sel) -> *mut NSArray {
        let array = Id<NSArray, Owned>::from(vec![...]);
        array.autorelease(pool) // Uhh, we don't have a pool from anywhere; it is implicit in Objective-C
    }
    let mut decl = ClassDecl::new("MyView", class!(NSView)).unwrap();
    decl.add_method(
        sel!(validAttributesForMarkedText),
        valid_attributes as extern "C" fn(&Object, Sel) -> *mut NSArray,
    );

See related: gfx-rs/metal-rs#222

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions