Skip to content

Commit

Permalink
Fix conflicts with same method names across different modules on iOS
Browse files Browse the repository at this point in the history
This is done by prefixig method names with the module name
  • Loading branch information
erksch committed Feb 22, 2025
1 parent 1558ddd commit 1d925d7
Show file tree
Hide file tree
Showing 9 changed files with 251 additions and 282 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## unreleased

- Fix conflicts with same method names across different modules on iOS by prefixing method names

## v0.1.0-rc.2

- Fix errors with boolean types in method return and flow types on iOS
Expand Down
5 changes: 5 additions & 0 deletions example/flutter/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,11 @@ class _MyAppState extends State<MyApp> {

final mySecondTestModule = MySecondTestModule();

print(
"myTestModule.methodWithSameNameAsInOtherModule: ${await myTestModule.methodWithSameNameAsInOtherModule("abc")}");
print(
"mySecondTestModule.methodWithSameNameAsInOtherModule: ${await mySecondTestModule.methodWithSameNameAsInOtherModule(123)}");

print(
"mySecondTestModule.testMethod: ${await mySecondTestModule.testMethod()}");

Expand Down
17 changes: 16 additions & 1 deletion example/flutter/lib/MySecondTestModule.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ final Stream<MyDataClass> dataClassEvents = const EventChannel('MySecondTestModu
Future<String> testMethod() async {

final invokeResult = await methodChannelToNative.invokeMethod<String>(
'testMethod',
'MySecondTestModule_testMethod',
[],
);

Expand All @@ -32,4 +32,19 @@ final Stream<MyDataClass> dataClassEvents = const EventChannel('MySecondTestModu

return result;
}
Future<int> methodWithSameNameAsInOtherModule(int value) async {

final invokeResult = await methodChannelToNative.invokeMethod<int>(
'MySecondTestModule_methodWithSameNameAsInOtherModule',
[value],
);

if (invokeResult == null) {
throw PlatformException(code: '1', message: 'Method methodWithSameNameAsInOtherModule failed');
}

final result = invokeResult;

return result;
}
}
85 changes: 50 additions & 35 deletions example/flutter/lib/MyTestModule.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ final Stream<MyDataClass> dataClassEvents = const EventChannel('MyTestModule_dat

Future<int?> next(int? previous) async {
return await methodChannelToNative.invokeMethod<int>(
'intState',
'MyTestModule_intState',
[previous]
);
}
Expand Down Expand Up @@ -60,7 +60,7 @@ final Stream<MyDataClass> dataClassEvents = const EventChannel('MyTestModule_dat

Future<String?> next(String? previous) async {
return await methodChannelToNative.invokeMethod<String>(
'dataClassState',
'MyTestModule_dataClassState',
[previous]
);
}
Expand Down Expand Up @@ -95,7 +95,7 @@ final Stream<MyDataClass> dataClassEvents = const EventChannel('MyTestModule_dat

Future<String?> next(String? previous) async {
return await methodChannelToNative.invokeMethod<String>(
'parameterizedDataClassState',
'MyTestModule_parameterizedDataClassState',
[previous, dataSerialized]
);
}
Expand Down Expand Up @@ -130,7 +130,7 @@ final Stream<MyDataClass> dataClassEvents = const EventChannel('MyTestModule_dat

Future<String?> next(String? previous) async {
return await methodChannelToNative.invokeMethod<String>(
'boolState',
'MyTestModule_boolState',
[previous]
);
}
Expand Down Expand Up @@ -165,7 +165,7 @@ final Stream<MyDataClass> dataClassEvents = const EventChannel('MyTestModule_dat

Future<int?> next(int? previous) async {
return await methodChannelToNative.invokeMethod<int>(
'intStateAdd',
'MyTestModule_intStateAdd',
[previous, num]
);
}
Expand Down Expand Up @@ -196,12 +196,12 @@ final Stream<MyDataClass> dataClassEvents = const EventChannel('MyTestModule_dat
}
Future<void> unitMethod() async {

await methodChannelToNative.invokeMethod<void>('unitMethod', []);
await methodChannelToNative.invokeMethod<void>('MyTestModule_unitMethod', []);
}
Future<String> simpleMethod() async {

final invokeResult = await methodChannelToNative.invokeMethod<String>(
'simpleMethod',
'MyTestModule_simpleMethod',
[],
);

Expand All @@ -216,7 +216,7 @@ Future<String> simpleMethod() async {
Future<String> stringMethod(String value) async {

final invokeResult = await methodChannelToNative.invokeMethod<String>(
'stringMethod',
'MyTestModule_stringMethod',
[value],
);

Expand All @@ -231,7 +231,7 @@ Future<String> stringMethod(String value) async {
Future<String?> nullableStringMethod(String? value) async {

final invokeResult = await methodChannelToNative.invokeMethod<String?>(
'nullableStringMethod',
'MyTestModule_nullableStringMethod',
[value],
);
final result = invokeResult;
Expand All @@ -240,7 +240,7 @@ Future<String?> nullableStringMethod(String? value) async {
Future<int> intMethod(int value) async {

final invokeResult = await methodChannelToNative.invokeMethod<int>(
'intMethod',
'MyTestModule_intMethod',
[value],
);

Expand All @@ -255,7 +255,7 @@ Future<int> intMethod(int value) async {
Future<double> doubleMethod(double value) async {

final invokeResult = await methodChannelToNative.invokeMethod<double>(
'doubleMethod',
'MyTestModule_doubleMethod',
[value],
);

Expand All @@ -270,7 +270,7 @@ Future<double> doubleMethod(double value) async {
Future<bool> boolMethod(bool value) async {
final valueSerialized = value.toString();
final invokeResult = await methodChannelToNative.invokeMethod<String>(
'boolMethod',
'MyTestModule_boolMethod',
[valueSerialized],
);

Expand All @@ -282,15 +282,30 @@ Future<bool> boolMethod(bool value) async {

return result;
}
Future<String> methodWithSameNameAsInOtherModule(String value) async {

final invokeResult = await methodChannelToNative.invokeMethod<String>(
'MyTestModule_methodWithSameNameAsInOtherModule',
[value],
);

if (invokeResult == null) {
throw PlatformException(code: '1', message: 'Method methodWithSameNameAsInOtherModule failed');
}

final result = invokeResult;

return result;
}
Future<void> parameterizedMethod(String a, int b, bool c, double d) async {
final cSerialized = c.toString();
await methodChannelToNative.invokeMethod<void>('parameterizedMethod', [a, b, cSerialized, d]);
await methodChannelToNative.invokeMethod<void>('MyTestModule_parameterizedMethod', [a, b, cSerialized, d]);
}
Future<DateTime> localDateTimeMethod(DateTime localDateTime) async {
if (localDateTime.isUtc) throw ArgumentError('localDateTime must not be in UTC');
final localDateTimeSerialized = localDateTime.toIso8601String();
final invokeResult = await methodChannelToNative.invokeMethod<String>(
'localDateTimeMethod',
'MyTestModule_localDateTimeMethod',
[localDateTimeSerialized],
);

Expand All @@ -305,7 +320,7 @@ final localDateTimeSerialized = localDateTime.toIso8601String();
Future<TimeOfDay> localTimeMethod(TimeOfDay localTime) async {
final localTimeSerialized = "${localTime.hour.toString().padLeft(2, '0')}:${localTime.minute.toString().padLeft(2, '0')}";
final invokeResult = await methodChannelToNative.invokeMethod<String>(
'localTimeMethod',
'MyTestModule_localTimeMethod',
[localTimeSerialized],
);

Expand All @@ -321,7 +336,7 @@ Future<DateTime> localDateMethod(DateTime localDate) async {
if (localDate.isUtc) throw ArgumentError('localDate must not be in UTC');
final localDateSerialized = localDate.toIso8601String().split('T').first;
final invokeResult = await methodChannelToNative.invokeMethod<String>(
'localDateMethod',
'MyTestModule_localDateMethod',
[localDateSerialized],
);

Expand All @@ -336,7 +351,7 @@ final localDateSerialized = localDate.toIso8601String().split('T').first;
Future<Duration> durationMethod(Duration duration) async {
final durationSerialized = duration.toIso8601String();
final invokeResult = await methodChannelToNative.invokeMethod<String>(
'durationMethod',
'MyTestModule_durationMethod',
[durationSerialized],
);

Expand All @@ -352,7 +367,7 @@ Future<DateTime> instantMethod(DateTime instant) async {
if (!instant.isUtc) throw ArgumentError('instant must be in UTC');
final instantSerialized = instant.toIso8601String();
final invokeResult = await methodChannelToNative.invokeMethod<String>(
'instantMethod',
'MyTestModule_instantMethod',
[instantSerialized],
);

Expand All @@ -367,7 +382,7 @@ final instantSerialized = instant.toIso8601String();
Future<List<String>> stringListMethod(List<String> list) async {
final listSerialized = jsonEncode(list.map((e) => e).toList());
final invokeResult = await methodChannelToNative.invokeMethod<String>(
'stringListMethod',
'MyTestModule_stringListMethod',
[listSerialized],
);

Expand All @@ -384,7 +399,7 @@ return element as String;
Future<List<List<String>>> nestedListMethod(List<List<String>> list) async {
final listSerialized = jsonEncode(list.map((e) => e.map((e) => e).toList()).toList());
final invokeResult = await methodChannelToNative.invokeMethod<String>(
'nestedListMethod',
'MyTestModule_nestedListMethod',
[listSerialized],
);

Expand All @@ -403,7 +418,7 @@ return element as String;
Future<List<MyDataClass>> dataClassListMethod(List<MyDataClass> list) async {
final listSerialized = jsonEncode(list.map((e) => e).toList());
final invokeResult = await methodChannelToNative.invokeMethod<String>(
'dataClassListMethod',
'MyTestModule_dataClassListMethod',
[listSerialized],
);

Expand All @@ -420,7 +435,7 @@ return MyDataClass.fromJson(element);
Future<List<List<MyDataClass>>> nestedDataClassListMethod(List<List<MyDataClass>> list) async {
final listSerialized = jsonEncode(list.map((e) => e.map((e) => e).toList()).toList());
final invokeResult = await methodChannelToNative.invokeMethod<String>(
'nestedDataClassListMethod',
'MyTestModule_nestedDataClassListMethod',
[listSerialized],
);

Expand All @@ -439,7 +454,7 @@ return MyDataClass.fromJson(element);
Future<Map<String, int>> mapMethod(Map<String, int> map) async {
final mapSerialized = jsonEncode(map.map((k, v) => MapEntry(k, v)));
final invokeResult = await methodChannelToNative.invokeMethod<String>(
'mapMethod',
'MyTestModule_mapMethod',
[mapSerialized],
);

Expand All @@ -456,7 +471,7 @@ return MapEntry(key, value as int);
Future<MyDataObject> objectMethod(MyDataObject obj) async {
final objSerialized = jsonEncode(obj.toJson());
final invokeResult = await methodChannelToNative.invokeMethod<String>(
'objectMethod',
'MyTestModule_objectMethod',
[objSerialized],
);

Expand All @@ -471,7 +486,7 @@ Future<MyDataObject> objectMethod(MyDataObject obj) async {
Future<MySealedData> sealedMethod(MySealedData obj) async {
final objSerialized = jsonEncode(MySealedData.toJson(obj));
final invokeResult = await methodChannelToNative.invokeMethod<String>(
'sealedMethod',
'MyTestModule_sealedMethod',
[objSerialized],
);

Expand All @@ -486,7 +501,7 @@ Future<MySealedData> sealedMethod(MySealedData obj) async {
Future<MyDateClass> dateClassMethod(MyDateClass obj) async {
final objSerialized = jsonEncode(obj.toJson());
final invokeResult = await methodChannelToNative.invokeMethod<String>(
'dateClassMethod',
'MyTestModule_dateClassMethod',
[objSerialized],
);

Expand All @@ -501,7 +516,7 @@ Future<MyDateClass> dateClassMethod(MyDateClass obj) async {
Future<MySealedDataWithProps> sealedWithPropsMethod(MySealedDataWithProps obj) async {
final objSerialized = jsonEncode(MySealedDataWithProps.toJson(obj));
final invokeResult = await methodChannelToNative.invokeMethod<String>(
'sealedWithPropsMethod',
'MyTestModule_sealedWithPropsMethod',
[objSerialized],
);

Expand All @@ -516,7 +531,7 @@ Future<MySealedDataWithProps> sealedWithPropsMethod(MySealedDataWithProps obj) a
Future<MyDataClassWithSealed> classWithSealedPropMethod(MyDataClassWithSealed obj) async {
final objSerialized = jsonEncode(obj.toJson());
final invokeResult = await methodChannelToNative.invokeMethod<String>(
'classWithSealedPropMethod',
'MyTestModule_classWithSealedPropMethod',
[objSerialized],
);

Expand All @@ -531,7 +546,7 @@ Future<MyDataClassWithSealed> classWithSealedPropMethod(MyDataClassWithSealed ob
Future<MyEnum> enumMethod(MyEnum entry) async {
final entrySerialized = jsonEncode(entry.name);;
final invokeResult = await methodChannelToNative.invokeMethod<String>(
'enumMethod',
'MyTestModule_enumMethod',
[entrySerialized],
);

Expand All @@ -546,7 +561,7 @@ Future<MyEnum> enumMethod(MyEnum entry) async {
Future<List<MyEnum>> enumListMethod(List<MyEnum> entries) async {
final entriesSerialized = jsonEncode(entries.map((e) => e.name).toList());
final invokeResult = await methodChannelToNative.invokeMethod<String>(
'enumListMethod',
'MyTestModule_enumListMethod',
[entriesSerialized],
);

Expand All @@ -563,7 +578,7 @@ return MyEnum.values.byName(element);
Future<Map<String, MyEnum>> enumMapMethod(Map<String, MyEnum> entries) async {
final entriesSerialized = jsonEncode(entries.map((k, v) => MapEntry(k, v.name)));
final invokeResult = await methodChannelToNative.invokeMethod<String>(
'enumMapMethod',
'MyTestModule_enumMapMethod',
[entriesSerialized],
);

Expand All @@ -580,7 +595,7 @@ return MapEntry(key, MyEnum.values.byName(value));
Future<Map<String, List<Map<String, MyDataClass>>>> mixedMethod(Map<String, List<Map<String, MyDataClass>>> map) async {
final mapSerialized = jsonEncode(map.map((k, v) => MapEntry(k, v.map((e) => e.map((k, v) => MapEntry(k, v))).toList())));
final invokeResult = await methodChannelToNative.invokeMethod<String>(
'mixedMethod',
'MyTestModule_mixedMethod',
[mapSerialized],
);

Expand All @@ -601,7 +616,7 @@ return MapEntry(key, MyDataClass.fromJson(value));
Future<MyDataClass> dataClassMethod(MyDataClass data) async {
final dataSerialized = jsonEncode(data.toJson());
final invokeResult = await methodChannelToNative.invokeMethod<String>(
'dataClassMethod',
'MyTestModule_dataClassMethod',
[dataSerialized],
);

Expand All @@ -615,12 +630,12 @@ Future<MyDataClass> dataClassMethod(MyDataClass data) async {
}
Future<void> suspendUnitMethod() async {

await methodChannelToNative.invokeMethod<void>('suspendUnitMethod', []);
await methodChannelToNative.invokeMethod<void>('MyTestModule_suspendUnitMethod', []);
}
Future<String> suspendStringMethod() async {

final invokeResult = await methodChannelToNative.invokeMethod<String>(
'suspendStringMethod',
'MyTestModule_suspendStringMethod',
[],
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ class MyTestModule(coroutineScope: CoroutineScope) {
@FlutterMethod
fun boolMethod(value: Boolean): Boolean = value

@FlutterMethod
fun methodWithSameNameAsInOtherModule(value: String): String = value

@FlutterMethod
fun parameterizedMethod(
a: String,
Expand Down Expand Up @@ -241,6 +244,9 @@ class MySecondTestModule(coroutineScope: CoroutineScope) {
@FlutterMethod
fun testMethod(): String = "Hello from Kotlin!!!"

@FlutterMethod
fun methodWithSameNameAsInOtherModule(value: Int): Int = value

@FlutterFlow
val intEvents: Flow<Int> = _intState

Expand Down
Loading

0 comments on commit 1d925d7

Please sign in to comment.