Skip to content

Improving how we map protocols #291

@madsmtm

Description

@madsmtm

Continuing on the work done in #250.

Currently

A protocol is mapped to a struct that impls Message, which allows using it in Id.
This allows similar patterns as id<ProtocolName> would do in Objective-C, but has a lot of tradeoffs, including:

  1. Calling a method on a protocol is more cumbersome than doing it on a normal struct.

    use icrate::Foundation::{NSLock, NSLocking};
    
    let obj = NSLock::new();
    
    // Not possible to call `lock` automatically, we have to convert it to a protocol object first
    // obj.lock();
    
    let proto: &NSLocking = obj.as_protocol();
    proto.lock();
    proto.unlock();
  2. Protocol class methods are impossible to do

    use icrate::Foundation::NSString;
    let res: bool = unsafe { msg_send![NSString::class(), supportsSecureCoding] };
  3. Calling methods on protocols that has multiple parent protocols is cumbersome:

    use icrate::AppKit::{NSTextCheckingClient, NSTextInputClient, NSTextInputTraits};
    let proto: &NSTextCheckingClient = ...; // Inherits NSTextInputClient and NSTextInputTraits
    proto.addAnnotations_range(...);
    
    // proto.hasMarkedText();
    let parent1: &NSTextInputClient = proto.as_protocol();
    parent1.hasMarkedText();
    
    // proto.autocorrectionType();
    let parent2: &NSTextInputTraits = proto.as_protocol();
    parent2.autocorrectionType();

Ideally

Ideally the constraints outlined above would be gone

  1. use icrate::Foundation::{NSLock, NSLocking};
    
    let obj = NSLock::new();
    
    obj.lock(); // Calls -[NSLocking lock]
    
    // Still possible
    let proto: &NSLocking = obj.as_protocol();
    
    proto.unlock();
  2. use icrate::Foundation::{NSString, NSSecureCoding};
    let res = NSString::supportsSecureCoding();
  3. use icrate::AppKit::{NSTextCheckingClient, NSTextInputClient, NSTextInputTraits};
    let proto: &NSTextCheckingClient = ...;
    proto.addAnnotations_range(...);
    proto.hasMarkedText();
    proto.autocorrectionType();

Idea

Maybe we could use something like Newtype<dyn MyProtocol> in place of &MyProtocol (since we can't override the behaviour of &dyn MyProtocol)? And do specialized stuff in Id to handle Id<dyn MyProtocol>?

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-frameworkAffects the framework crates and the translator for themA-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