-
Notifications
You must be signed in to change notification settings - Fork 92
Description
The package maplibre is very close to a complete native interop solution. The only outstanding problem is finding a solution for the currently malfunctioning callback functions.
I'd like to call the following ObjC method from Dart that uses a completion callback:
- (void)clearAmbientCacheWithCompletionHandler:(void (^)(NSError *_Nullable error))completion;- (void)clearAmbientCacheWithCompletionHandler:(void (^)(NSError *_Nullable error))completion {
_mbglDatabaseFileSource->clearAmbientCache([&, completion](std::exception_ptr exception){
NSError *error;
if (completion) {
if (exception) {
error = [NSError errorWithDomain:MLNErrorDomain code:MLNErrorCodeModifyingOfflineStorageFailed userInfo:@{
NSLocalizedDescriptionKey: @(mbgl::util::toString(exception).c_str()),
}];
}
dispatch_async(dispatch_get_main_queue(), [&, completion, error](void) {
completion(error);
});
}
});
}
ffigen generates the following binding with this tool/ffigen.dart configuration.
/// Construction methods for `objc.ObjCBlock<ffi.Void Function(objc.NSError?)>`.
abstract final class ObjCBlock_ffiVoid_NSError {
// ...
static objc.ObjCBlock<ffi.Void Function(objc.NSError?)> listener(void Function(objc.NSError? ) fn,
{bool keepIsolateAlive = true}) {
final raw = objc.newClosureBlock(_listenerCallable.nativeFunction.cast(),
(ffi.Pointer<objc.ObjCObjectImpl> arg0) => fn(arg0.address == 0 ? null : objc.NSError.fromPointer(arg0, retain: false, release: true)), keepIsolateAlive);
final wrapper = _NativeLibrary_wrapListenerBlock_xtuoz7(raw);
objc.objectRelease(raw.cast());
return objc.ObjCBlock<ffi.Void Function(objc.NSError?)>(wrapper, retain: false, release: true);
}
// ...
}
// ...
/// Clears the ambient cache by deleting resources. This method does not affect
/// resources shared with offline regions.
///
/// @param completion The completion handler to call once resources from the
/// ambient cache have been cleared. This handler is executed asynchronously on
/// the main queue.
void clearAmbientCacheWithCompletionHandler(objc.ObjCBlock<ffi.Void Function(objc.NSError?)> completion) {
_objc_msgSend_f167m6(object$.ref.pointer, _sel_clearAmbientCacheWithCompletionHandler_, completion.ref.pointer);
}When I now try to call the method:
final storage = MLNOfflineStorage.getSharedOfflineStorage();
// later
storage.clearAmbientCacheWithCompletionHandler(
ObjCBlock_ffiVoid_NSError.listener((error) {}),
);I get the following exception in the console:
[ERROR:flutter/runtime/dart_vm_initializer.cc(40)] Unhandled Exception: Invalid argument(s): Couldn't resolve native function '_NativeLibrary_wrapListenerBlock_xtuoz7' in 'package:maplibre_ios/maplibre_ffi.g.dart' : No asset with id 'package:maplibre_ios/maplibre_ffi.g.dart' found. Available native assets: package:objective_c/objective_c.dylib. Attempted to fallback to process lookup. dlsym(RTLD_DEFAULT, _NativeLibrary_wrapListenerBlock_xtuoz7): symbol not found.
#0 Native._ffi_resolver.#ffiClosure0 (dart:ffi-patch/ffi_patch.dart)
#1 Native._ffi_resolver_function (dart:ffi-patch/ffi_patch.dart:1943:20)
#2 _NativeLibrary_wrapListenerBlock_xtuoz7 (package:maplibre_ios/maplibre_ffi.g.dart)
#3 ObjCBlock_ffiVoid_NSError.listener (package:maplibre_ios/maplibre_ffi.g.dart:6549:21)
#4 OfflineManagerIos.clearAmbientCache (package:maplibre/src/platform/ios/offline_manager.dart:29:33)
#5 _OfflinePageState.build.<anonymous closure>.<anonymous closure> (package:maplibre_example/offl<…>
This issue might be related to the problem described in #1475.
I am running the example app with the Swift Package Manager enabled. The dependency graph looks like this maplibre_example -> maplibre -> maplibre_ios (needed because of flutter/flutter#148424 / flutter/flutter#63240).
The native MapLibre iOS SDK gets added like this:
let package = Package(
name: "maplibre_ios",
platforms: [
.iOS("12.0"),
],
products: [
.library(name: "maplibre-ios", targets: ["maplibre_ios"]),
],
dependencies: [
.package(url: "https://github.com/maplibre/maplibre-gl-native-distribution", .upToNextMinor(from: "6.21.0")),
],
targets: [
.target(
name: "maplibre_ios",
dependencies: [
.product(name: "MapLibre", package: "maplibre-gl-native-distribution"),
],
cSettings: [
.headerSearchPath("include/maplibre_ios"),
]
),
]
)My setup is running on the stable Flutter 3.38.5 release.
Output of`flutter doctor
% flutter doctor -v
[✓] Flutter (Channel stable, 3.38.5, on macOS 26.1 25B78 darwin-arm64, locale de-DE) [180ms]
• Flutter version 3.38.5 on channel stable at /Users/joscha/development/flutter
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision f6ff1529fd (2 weeks ago), 2025-12-11 11:50:07 -0500
• Engine revision 1527ae0ec5
• Dart version 3.10.4
• DevTools version 2.51.1
• Feature flags: enable-web, enable-linux-desktop, enable-macos-desktop, enable-windows-desktop, enable-android, enable-ios, cli-animations, enable-native-assets,
enable-swift-package-manager, omit-legacy-version-file, enable-lldb-debugging
[!] Android toolchain - develop for Android devices (Android SDK version 35.0.1) [245ms]
• Android SDK at /Users/joscha/Library/Android/sdk
• Emulator version 35.3.11.0 (build_id 12836668) (CL:N/A)
✗ cmdline-tools component is missing.
Try installing or updating Android Studio.
Alternatively, download the tools from https://developer.android.com/studio#command-line-tools-only and make sure to set the ANDROID_HOME environment variable.
See https://developer.android.com/studio/command-line for more details.
✗ Android license status unknown.
Run `flutter doctor --android-licenses` to accept the SDK licenses.
See https://flutter.dev/to/macos-android-setup for more details.
[✓] Xcode - develop for iOS and macOS (Xcode 26.1) [430ms]
• Xcode at /Applications/Xcode.app/Contents/Developer
• Build 17B55
• CocoaPods version 1.16.2
[✗] Chrome - develop for the web (Cannot find Chrome executable at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome) [4ms]
! Cannot find Chrome. Try setting CHROME_EXECUTABLE to a Chrome executable.
[✓] Connected device (2 available) [5,6s]
• iPhone 16e (mobile) • 072F1161-B1B2-4599-9E41-80726EFEB0E8 • ios • com.apple.CoreSimulator.SimRuntime.iOS-26-1 (simulator)
• macOS (desktop) • macos • darwin-arm64 • macOS 26.1 25B78 darwin-arm64
[✓] Network resources [319ms]
• All expected network resources are available.
! Doctor found issues in 2 categories.Metadata
Metadata
Assignees
Labels
Type
Projects
Status