Description
In Apple's Objective-C headers, most classes and methods are annotated with an availability attribute such as API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0))
; this is absolutely a great idea (!!!), it very cleanly allows you to mark which APIs you may use, and which ones are not usable on your current deployment target.
We should have some way of doing the same as @available
in Objective-C; however, since we are not a compiler like clang
is, this is quite tricky!
A quick demonstration of what I want:
- Declare an API which is only available on a specific deployment target
#[cfg_available(macos = 10.10, ..)] #[sel(doSomething:)] fn doSomething(&self, arg: i32);
- Prevent the user from using said API if their deployment target is not high enough:
// MACOSX_DEPLOYMENT_TARGET=10.7 obj.doSomething(32); // Fails (ideally at compile time, otherwise with debug assertions at runtime) // MACOSX_DEPLOYMENT_TARGET=10.10 obj.doSomething(32); // Works
- Allow the user (usually libraries) to use the API if they've verified that the target version is high enough (this uses a dynamic runtime check except if the deployment target is high enough). Done in Implement runtime availability checking #661.
if available!(macos = 10.12, ..) { // Anything higher than what `doSomething` needs obj.doSomething(32); // Works no matter the deployment target }
- When declaring a class and overriding methods, if you know when the method was added (and hence, when it will be called), communicate this availability to the body of the function:
#[cfg_available(macos = 10.10, ..)] // Same as superclass' #[sel(doSomething:)] fn doSomething(&self, arg: i32) { // Allowed to do things only available on macOS 10.10 and above }
For this, Contexts and capabilities come to mind, similar to how it would be useful for autorelease pools, but alas, we can't do that yet, so this will probably end up as a debug assertions runtime check.
See also the original SSheldon/rust-objc#111, a WIP implementation can be found in #212.