Skip to content

[API Proposal]: Add back ObsoletedInOSPlatformAttribute for .NET 7 #68557

@rolfbjarne

Description

@rolfbjarne

Background and Motivation

[This is pretty much a copy of #47601, with an additional aggravating scenario we've run into]

API Proposal

Original specs

This was removed in 5.0 RC: dotnet/docs#20635

ObsoletedInOSPlatformAttribute was removed, as this annotation is not needed at this time

With the addition of mobile platforms we think the need/time has come :-)

API Usage

Apple commonly obsoletes API and provide better alternatives for them. The headers (both C and Objective-C) includes macros that help developers (and the Xcode IDE) select the best API for the OS version being targeted.

The legacy Xamarin SDKs (iOS/Mac) annotate the API with the similar attributes. They are:

  1. [Introduced]: specifies in which OS version an API was introduced. This maps perfectly to [SupportedOSPlatform ("ios10.0")]
  2. [Obsoleted]: Apple will often make API obsolete, and sometimes tell the user which API they're to use instead. This might map to [UnsupportedOSPlatform ("ios15.0")], but there's no way to specify a custom message.
  3. [Deprecated]: Some time after an API becomes obsolete, they might become deprecated (which generally means they will be rejected if submitted to one of the Apple App Stores). In this case Apple might also give a message telling the user the better API to use. This might map to [UnsupportedOSPlatform ("ios15.0")], but there's no way to map a custom message.
  4. [Unavailable]: specifies an API which is not available anymore (and which we can't remove because it would be a breaking change). This maps perfectly to [UnsupportedOSPlatform ("ios")]

The problematic attributes are [Obsoleted] and [Deprecated], because the [UnsupportedOSPlatform] attribute doesn't let us give the user a custom message (such as telling them what to do instead).

We've opted for using the [Obsolete] attribute instead (as was suggested in #47601): [Obsolete ("Starting with iOS 15.0, use XYZ instead")].

The problem is the following scenario:

  1. Developer needs to keep their app working an older iOS version, say iOS 14.
  2. Apple obsoleted some API in iOS 15, providing an alternative.

The only way to make the build warning-free, is by doing something like this:

#pragma warning disable 618
    CalliOS14API ();
#pragma warning restore 618

adding a version check won't change anything:

    if (checkForiOS15) {
        CalliOS15API ();
    } else {
#pragma warning disable 618
        CalliOS14API ();
#pragma warning restore 618
    }

I believe that adding back the [ObsoletedInOSPlatform] (which had a Message property) would allow us to improve this, so that app developers won't get warning about deprecated code that will never run on platforms where the API is deprecated due to version checks.

Ref: dotnet/macios#10170

For reference, we got this design from how Apple/clang declares it: https://clang.llvm.org/docs/AttributeReference.html#availability

Attribute Explanation
introduced=version The first version in which this declaration was introduced.
deprecated=version The first version in which this declaration was deprecated, meaning that users should migrate away from this API.
 obsoleted=version  The first version in which this declaration was obsoleted, meaning that it was removed completely and can no longer be used. 
 unavailable This declaration is never available on this platform.

Alternative Designs

Alternatively it might be possible to add a Message property to the [UnsupportedOSPlatform] attribute.

Risks

The lack of a solution means that users will have a hard time making their build warning-free.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions