Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate external categories #574

Merged
merged 3 commits into from
Feb 5, 2024
Merged

Generate external categories #574

merged 3 commits into from
Feb 5, 2024

Conversation

madsmtm
Copy link
Owner

@madsmtm madsmtm commented Feb 4, 2024

Categories are a way for Objective-C code to add extra methods to a class. There are basically two ways we could handle these in header-translator:

  1. Emit extern_methods! directly on the class (done currently).

    This breaks when the class is defined in a different library/framework than the category, because of Rust's coherence rules.

  2. Create a trait, and implement that for the class (done in uikit-sys, and now by extern_category!).

    One problem here is that the category name is not part of the API in Objective-C, so we actually have no stable name to refer to. Relatedly, it's annoying to have to import category traits with confusing names all the time.

Both approaches have issues, so I've tried to strike a nice balance; we now emit extern_methods! when the category is defined in the same library/framework as the class, and extern_category! otherwise. This doesn't completely resolve the issues around categories not having a stable name, but it does somewhat alleviate them.

This allows us to fix #531, we now emit the missing key-value coding categories (and other such categories on NSObject). This should also help with splitting icrate up into multiple crates in the future, instead of it being a big monolithic one. Finally, this is required for header-translator to work on user-defined categories in the future (see #501).

CC @simlay as you've gone with the second approach in bindgen's Objective-C support, wanted to hear your thoughts about this combined solution? I note that yours is currently better, since it implements the category trait for subclasses as well.

@madsmtm madsmtm added enhancement New feature or request A-objc2 Affects the `objc2`, `objc2-exception-helper` and/or `objc2-encode` crates A-framework Affects the framework crates and the translator for them labels Feb 4, 2024
These are useful for categories defined on classes outside the current library, since while `icrate` is currently monolithic and this sort of pattern works, that will probably change in the future.
@simlay
Copy link
Collaborator

simlay commented Feb 5, 2024

Both approaches have issues, so I've tried to strike a nice balance; we now emit extern_methods! when the category is defined in the same library/framework as the class, and extern_category! otherwise. This doesn't completely resolve the issues around categories not having a stable name, but it does somewhat alleviate them.

Yeah, I think this is a reasonable trade off. I think the negative to this approach is that debugging/understanding is harder. There's two possible ways a function is added to a rust-side class - importing the trait that the category implements (a class has a category from a different library/framework) vs not.

The ergonomics of including a bunch of traits just for a few specific functions was pretty rough.

Semirelated, I wish there was a good way to do source maps/links to apple docs for things.

@madsmtm
Copy link
Owner Author

madsmtm commented Feb 5, 2024

Both approaches have issues, so I've tried to strike a nice balance; we now emit extern_methods! when the category is defined in the same library/framework as the class, and extern_category! otherwise. This doesn't completely resolve the issues around categories not having a stable name, but it does somewhat alleviate them.

Yeah, I think this is a reasonable trade off. I think the negative to this approach is that debugging/understanding is harder. There's two possible ways a function is added to a rust-side class - importing the trait that the category implements (a class has a category from a different library/framework) vs not.

Thanks for the feedback; I'll try to document it at some point, tracking in #576.

Semirelated, I wish there was a good way to do source maps/links to apple docs for things.

Well, there is no good way, but there probably is a way, tracking in #309.

@madsmtm madsmtm merged commit 83b1fbb into master Feb 5, 2024
19 checks passed
@madsmtm madsmtm deleted the better-categories branch February 5, 2024 12:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-framework Affects the framework crates and the translator for them A-objc2 Affects the `objc2`, `objc2-exception-helper` and/or `objc2-encode` crates enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Generate KVO add/remove observer methods for NSProgress
2 participants