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):
- 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)
}
- 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)) }
})
}
- 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
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):
See related: gfx-rs/metal-rs#222