dart-lang / native

Dart packages related to FFI and native assets bundling.
BSD 3-Clause "New" or "Revised" License
149 stars 42 forks source link

Document a pattern to replace `@available` (Obj-C) / `#available` (Swift) #1588

Open stuartmorgan opened 2 weeks ago

stuartmorgan commented 2 weeks ago

iOS/macOS development has a common pattern where an SDK introduces a new preferred API and deprecates the old API at the same time. In the old days this was a pretty painful experience for developers, but at some point Apple introduced the available system to make it much simpler and safer.

Main features:

  1. If you unconditionally call an API that's available on OS version N, but your minimum deployment target is <N, you get a development-time warning.
  2. If you correctly wrap that call in an available check, that warning goes away, and then you automatically have the logic to do whatever runtime conditional is necessary (usually calling the now-deprecated API in the else).

https://github.com/dart-lang/native/issues/300 covers throwing instead of crashing, but doesn't solve the problem that available and the associated warnings does, which is making it very easy to handle iOS version differences correctly, and very hard to accidentally fail to do so.

We should have a recommended pattern for doing the runtime check, and clearly document it somewhere as how to handle APIs that aren't available on newer OS versions. But if it's just an OS version check, that will still be significantly more error-prone than available because developers will be responsible for looking up every single API they are using to check its availability. If we want to replicate the same level of safety and ease of use that available provides, we would need to propagate version annotations through into the generated code in some way, somehow make the Dart analyzer aware of min native deployment version, and create new lints that replicate the warnings for missing checks.

stuartmorgan commented 2 weeks ago

Cross-reference: https://github.com/dart-lang/native/issues/1590 which is a similar issue on Android.

liamappelbe commented 2 weeks ago

Related: https://github.com/dart-lang/native/issues/1338. If you set a minimum target version, then ffigen won't generate bindigns for APIs that were deprecated before that version.

jmagman commented 2 weeks ago

image_picker_ios is an example in the wild: https://github.com/flutter/packages/blob/a717b0e189ad070a5acb1d0caf4a327c6d222f0c/packages/image_picker/image_picker_ios/ios/image_picker_ios/Sources/image_picker_ios/FLTImagePickerPlugin.m#L180