Dart 2.18: Objective-C- und Swift-Interop

Dec 20 2022
Verbesserte Interoperabilität, plattformspezifische Vernetzung, verbesserte Typinferenz und ein wichtiges Update unserer Null-Sicherheitssprachen-Roadmap Dart 2.18 sind heute verfügbar.

Verbesserte Interoperabilität, plattformspezifische Vernetzung, verbesserte Typinferenz und ein wichtiges Update unserer Roadmap für Null-Sicherheitssprachen

Dart 2.18 ist ab sofort verfügbar. Diese Version bietet eine Vorschau auf die Interoperabilität von Objective-C und Swift sowie ein neues iOS/macOS-Netzwerkpaket, das auf dieser Interoperabilität aufbaut. Es enthält außerdem eine verbesserte Typinferenz für generische Funktionen, Leistungsverbesserungen für asynchronen Code, neue pub.dev-Funktionen und eine Bereinigung unserer Tools und Kernbibliotheken.

Endlich haben wir die neuesten Null-Safety-Migrationsstatusnummern und ein wichtiges Roadmap-Update auf unserem Weg zu einem vollständig Null-Safe-Dart. Bitte bis zum Ende lesen!

Einführung von Dart in die Objective-C- und Swift-Interop

Wir haben im Jahr 2020 eine Vorschau der Dart Foreign Function Interface (FFI) zum Aufrufen nativer C-APIs vorgestellt und sie im März 2021 in Dart 2.12 veröffentlicht. Seit dieser Veröffentlichung hat eine große Auswahl an Paketen diese Funktion zur Integration in bestehende native C-APIs genutzt. Einige Beispiele sind file_picker, printing, win32, objectbox, realm, isar, tflite_flutterund dbus.

Das Dart-Team möchte, dass Dart die Interoperabilität mit allen Primärsprachen auf den Plattformen unterstützt, auf denen Dart läuft. Dart 2.18 erreicht den nächsten Meilenstein auf dem Weg zu diesem Ziel. Ihr Dart-Code kann Objective-C- und Swift-Code aufrufen, wie er typischerweise für APIs auf den Plattformen macOS und iOS verwendet wird. Dart unterstützt diesen Interop-Mechanismus in jeder App, von der CLI-App über Backend-Code bis hin zu einer Flutter-Benutzeroberfläche.

Dieser neue Mechanismus nutzt die Tatsache, dass Objective-C- und Swift-Code basierend auf API-Bindungen als C-Code verfügbar gemacht werden kann. Das Dart-API-Wrapper-Generierungstool ffigenkann diese Bindungen aus API-Headern erstellen. Schauen wir uns ein Beispiel an.

Zeitzonenbeispiel mit Objective-C

NSTimeZonemacOS verfügt über eine API zum Abfragen der in der Klasse bereitgestellten Zeitzoneninformationen . Sie können diese API nach der Zeitzone und dem UTC-Zeitzonenoffset abfragen , die der Benutzer für sein Gerät konfiguriert hat.

Die folgende Objective-C-Beispielanwendung verwendet diese Zeitzonen-API, um die Systemzeitzone und den GMT-Offset abzurufen:

Die App importiert Foundation.h, das die API-Header für die Apple Foundation-Bibliothek enthält. mainAls nächstes ruft es innerhalb der Methode die systemTimeZoneMethode aus der NSTimeZoneKlasse auf. Diese Methode gibt eine NSTimeZoneInstanz mit der ausgewählten Zeitzone auf dem Gerät zurück. Abschließend gibt die App zwei Zeilen an die Konsole aus, die den Namen der Zeitzone und den UTC-Offset in Stunden enthalten.

Wenn Sie diese App ausführen, sollte sie je nach Standort etwa Folgendes zurückgeben:

Timezone name: Europe/Copenhagen
Timezone offset GMT: 2 hours

Lassen Sie uns dieses Ergebnis mit Dart replizieren, indem wir das neue Objective-C-Interop verwenden.

Erstellen Sie zunächst eine neue Dart-CLI-App:

$ dart create timezones

Dadurch werden Objective-C-Bindungen für die Header ausgewählt NSTimeZone.hund nur die APIs in die NSTimeZoneSchnittstelle einbezogen. Um die Wrapper zu generieren, führen Sie Folgendes aus ffigen:

$ dart run ffigen

Das ist es! Diese neue Unterstützung ist ab dem heutigen Dart 2.18 in einem experimentellen Zustand verfügbar. Dadurch wird die allgemeine Interop-Unterstützung von Dart für den direkten Aufruf von macOS- und iOS-APIs verbessert. Dies wiederum ergänzt die Plugins von Flutter um neue Unterstützung, die in jeder Dart-App funktioniert und es Ihnen ermöglicht, macOS- und iOS-APIs direkt aus dem Dart-Code aufzurufen.

Wir freuen uns über Ihr Feedback. Teilen Sie uns mit, was funktioniert hat, was geändert werden könnte oder welche Probleme bei Ihnen aufgetreten sind, indem Sie in der Feedback-Ausgabe auf GitHub einen Kommentar abgeben. Weitere Informationen zu dieser Interoperabilität finden Sie im Leitfaden zur Interoperabilität von Objective-C und Swift .

Plattformspezifische http-Bibliotheken

Dart umfasst eine allgemeine, plattformübergreifende httpBibliothek. Mit dieser Bibliothek können Sie Code schreiben, ohne sich um Plattformspezifika kümmern zu müssen. Gelegentlich möchten Sie vielleicht Code schreiben, der speziell auf die Netzwerk-APIs einer bestimmten Hostplattform zugeschnitten ist.

Beispielsweise NSURLSessionerlaubt die Netzwerkbibliothek von Apple die Angabe, dass ein reines WLAN-Netzwerk vorhanden ist oder dass ein VPN erforderlich ist. Um diese Anwendungsfälle zu unterstützen, haben wir ein neues Netzwerkpaket für die macOS- und iOS-Plattformen erstellt cupertino_http. Dies baut auf dem neuen Objective-C-Interop auf, das im vorherigen Abschnitt erwähnt wurde. Es verwendet einen großen Satz von API-Wrappern , die aus den Netzwerk-APIs von Apple in Foundation generiert wurden .

Beispiel für eine http-Bibliothek aus Cupertino

Das folgende Beispiel stellt den http-Client einer Flutter-App so ein, dass er die cupertino_httpBibliothek auf macOS und iOS und die reguläre http-Bibliothek von Dart dart:ioauf anderen Plattformen verwendet:

Nach dieser Erstkonfiguration führt die App alle nachfolgenden Netzwerkaufrufe auf dem jeweiligen Client durch. get()Eine http- Anfrage sieht jetzt beispielsweise so aus:

Wenn Sie die gemeinsame Clientschnittstelle nicht verwenden können, können Sie die Netzwerk-APIs von Apple direkt über die cupertino_httpBibliothek aufrufen:

Plattformspezifische Vernetzung in Multiplattform-Apps

Bei der Entwicklung dieser Funktion blieb das Ziel bestehen, die Apps so plattformübergreifend wie möglich zu gestalten. Um dieses Ziel zu erreichen, haben wir unsere allgemeine Multiplattform- httpAPI für grundlegende HTTP-Vorgänge beibehalten und die Konfiguration der zu verwendenden Netzwerkbibliothek pro Plattform ermöglicht. Sie können die Menge an plattformspezifischem Code, den Sie schreiben müssen, minimieren, indem Sie die package:httpClient-API verwenden . Diese API kann pro Plattform konfiguriert, aber plattformunabhängig verwendet werden.

Dart 2.18 bietet experimentelle Unterstützung von zwei plattformspezifischen http-Bibliotheken, die die package:http Client-API unterstützen :

  • cupertino_httpbasierend auf NSURLSessionfür macOS/iOS.
  • cronet_httpBasierend auf Cronet , der auf Android beliebten Netzwerkbibliothek.

Verbesserte Typinferenz

Dart verwendet viele generische Funktionen. Betrachten Sie die foldMethode, die eine Sammlung von Elementen auf einen einzigen Wert reduziert. Das folgende Beispiel berechnet die Summe einer Liste von Ganzzahlen:

List<int> numbers = [1, 2, 3];
final sum = numbers.fold(0, (x, y) => x + y);
print(‘The sum of $numbers is $sum’);

line 2 • The operator ‘+’ can’t be unconditionally invoked because the receiver can be ‘null’.

final sum = numbers.fold(0, (int x, int y) => x + y);

Async-Leistungsverbesserungen

asyncDiese Version von Dart verbessert die Art und Weise, wie die Dart-VM die Methode und die async*/ sync*-Generatorfunktionen anwendet . Dadurch wird die Codegröße reduziert. Bei zwei großen internen Google-Apps konnten wir eine Reduzierung der AOT-Snapshot-Größe um etwa 10 % feststellen. Wir konnten auch eine Leistungssteigerung bei unseren Mikrobenchmarks feststellen.

Zu diesen Änderungen gehören zusätzliche kleine Verhaltensänderungen; Weitere Informationen finden Sie im Änderungsprotokoll .

pub.dev-Verbesserungen

Im Zusammenhang mit der Version 2.18 haben wir zwei Änderungen am pub.devPaket-Repository vorgenommen.

Einzelpersonen verwalten pub.devin ihrer Freizeit häufig Pakete, die auf veröffentlicht werden. Dies kann sowohl zeitlich als auch finanziell kostspielig sein. Um Sponsoring zu erleichtern, unterstützen wir jetzt einen neuen fundingTag im pubspec, der von Paketherausgebern verwendet werden kann, um Links zu einer oder mehreren Möglichkeiten zum Sponsoring des Pakets aufzulisten. pub.devDiese Links werden dann in der Seitenleiste angezeigt :

Weitere Informationen finden Sie in der pubspecDokumentation .

Darüber hinaus möchten wir ein reichhaltiges Ökosystem an Open-Source-Paketen fördern. Um dies hervorzuheben, vergibt die automatische Paketbewertung pub.devzusätzlich 10 Punkte für Pakete, die eine von OSI genehmigte Lizenz verwenden .

Ein paar bahnbrechende Änderungen

Dart legt großen Wert auf Einfachheit und Erlernbarkeit. Wir versuchen ständig, beim Hinzufügen neuer Funktionen ein sorgfältiges Gleichgewicht zu wahren. Eine Möglichkeit, die Dinge einfacher zu halten, besteht darin, historische Funktionen und APIs mit geringem Nutzen oder bessere Ersatzfunktionen zu entfernen. Dart 2.18 bereinigt Elemente in dieser Kategorie, einschließlich einiger kleinerer wichtiger Änderungen:

  • Wir haben das einheitliche dartCLI-Entwicklertool bereits im Oktober 2020 hinzugefügt. In 2.18 haben wir die Umstellung abgeschlossen. Diese Version entfernt die letzten beiden veralteten Tools dart2js(use dart compile js) und dartanalyzer(use dart analyze).
  • Mit der Einführung der Sprachversionierung pubwird eine neue Auflösungsdatei generiert: .dart_tool/package_config.json.Die vorherige Datei, .packages, verwendete ein Format, das keine Versionen enthalten konnte. Wir haben die Verwendung der .packagesDatei eingestellt. Wenn Sie .packagesDateien haben, können Sie diese löschen.
  • Mixins von Klassen, die nicht erweitert werden, Objectkönnen nicht verwendet werden (Breaking Change #48167 ). Dieses Verhalten war nie beabsichtigt.
  • Die uriEigenschaft von dart:io's RedirectExceptionwurde in nullable geändert (Breaking Change #49045 ).
  • Konstanten in dart:ioden Netzwerk-APIs von , die der SCREAMING_SNAKE-Konvention folgen, wurden entfernt (Breaking Change #34218 ; zuvor veraltet). Verwenden Sie stattdessen die entsprechenden LowerCamelCase-Konstanten.
  • Die Dart-VM stellt beim Beenden nicht mehr die anfänglichen Terminaleinstellungen wieder her. Programme, die die StdinEinstellungen ändern lineModeund echoModenun für die Wiederherstellung der Einstellungen beim Beenden des Programms verantwortlich sind (Breaking Change #45630 ).

Wir freuen uns sehr über die breite Nutzung von Null Safety seit der Beta-Veröffentlichung im November 2020 und der Veröffentlichung von Dart 2.12 im März 2021.

Erstens migrierten App-Entwickler der meisten gängigen Pakete pub.devauf Null-Sicherheit. Die Analyse zeigt, dass 100 % der Top-250 und 98 % der Top-1.000 am häufigsten verwendeten Pakete Nullsicherheit unterstützen.

Zweitens arbeiten die meisten App-Entwickler mit Codebasen mit vollständiger Null-Sicherheitsmigration. Das ist entscheidend. Die vollständige Sound-Null-Sicherheit von Dart tritt erst dann in Kraft, wenn Sie den gesamten Code und alle Abhängigkeiten (einschließlich transitiver) migrieren. Wir verfolgen dies per Telemetrie von flutter runBefehlen.

Die folgende Grafik zeigt die unsoliden vs. soliden Null-Sicherheitsausführungen von flutter run. Vor der Einführung der Nullsicherheit gab es beides nicht. Es folgte ein rasches Wachstum unsicherer Nullsicherheit. Als Apps mit der Migration auf Nullsicherheit begannen, führten die Entwickler eine Teilmigration durch. Einige Teile mussten noch migriert werden. Im Laufe der Zeit beobachten wir ein sehr gesundes Wachstum solider Null-Sicherheitssitzungen. Bis Ende letzten Monats gab es viermal mehr solide Null-Sicherheitssitzungen im Vergleich zu unsicheren. Wir hoffen, dass wir in den nächsten Quartalen den soliden Null-Sicherheitsansatz zu 100 % sehen werden!

Ein wichtiges Update der Null-Sicherheits-Roadmap

Die Unterstützung sowohl der unsoliden als auch der soliden Null-Sicherheit erhöht den Aufwand und die Komplexität.

Zunächst müssen Dart-Entwickler beide Modi erlernen und verstehen. Überprüfen Sie beim Lesen eines Teils des Dart-Codes die Sprachversion , um festzustellen, ob Typen standardmäßig ungleich Null sind (Dart 2.12 und höher) oder standardmäßig nullbar sind (Dart 2.11 und früher).

Zweitens verlangsamt die Unterstützung beider Modi in unseren Compilern und Laufzeiten die Weiterentwicklung des Dart SDK zur Unterstützung neuer Funktionen.

Basierend auf dem Mehraufwand durch unsichere Nullsicherheit und den sehr positiven Akzeptanzzahlen, die im vorherigen Abschnitt erwähnt wurden, ist es unser Ziel, nur noch solide Nullsicherheitsmodi zu unterstützen und Nicht-Nullsicherheitsmodi sowie unsichere Nullsicherheitsmodi abzuschaffen. Wir haben die Veröffentlichung vorläufig für Mitte 2023 geplant.

Dies würde bedeuten, dass die Unterstützung für Dart 2.11 und früher eingestellt wird. Pubspec-Dateien mit einer SDK-Einschränkung mit einer Untergrenze von weniger als 2,12 würden in Dart 3 und höher nicht mehr aufgelöst. In Quellcode, der Sprachmarkierungen enthält, würden diese fehlschlagen, wenn sie auf einen Wert unter 2.12 gesetzt würden (z. B. // @dart=2.9).

Wenn Sie auf Sound-Null-Sicherheit migriert haben, funktioniert Ihr Code in Dart 3 mit voller Null-Sicherheit. Wenn nicht, migrieren Sie jetzt! Weitere Informationen zu diesen Änderungen finden Sie in dieser GitHub-Ausgabe .

Zusammenfassung

Die neue Unterstützung für Interop, Netzwerk, Typinferenz und pub.devist ab sofort verfügbar. Um zu beginnen, können Sie die Dart 2.18-Version direkt herunterladen oder sie als Teil der heutigen Flutter 3.3 SDK-Version einbetten .