从字典访问 FlutterStandardTypedData 时出现“[__NSArrayI 数据]:无法识别的选择器”
Posted
技术标签:
【中文标题】从字典访问 FlutterStandardTypedData 时出现“[__NSArrayI 数据]:无法识别的选择器”【英文标题】:"[__NSArrayI data]: unrecognized selector" when accessing FlutterStandardTypedData from dictionary 【发布时间】:2020-01-19 21:40:27 【问题描述】:我正在尝试在 Flutter 中创建一个 Uint8List
,将其放入 JSON 字符串并将该字符串传递给本机代码。
这是我的 Flutter 代码:
final jsonObj =
"dataBuffer": dataBuffer, // dataBuffer is of type Uint8List
;
String encodedJson = json.encode(jsonObj);
await _channel.invokeMethod('testMethod', <String, dynamic>
'jsonObj': encodedJson,
);
这是原生 iOS 代码,我尝试在其中将 Uint8List
作为 FlutterStandardTypedData
从 JSON 字符串中取出:
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result
if ([@"testMethod" isEqualToString:call.method])
NSString* jsonString = (NSString*)call.arguments[@"jsonObj"];
NSData* jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSError *error = nil;
NSDictionary *responseObj = [NSJSONSerialization
JSONObjectWithData:jsonData
options:0
error:&error];
if(! error)
FlutterStandardTypedData *dataBufferJson = [responseObj objectForKey:@"dataBuffer"];
NSData *bufferData = [dataBufferJson data]; *** // Here is where the exception is thrown ***
当我尝试获取 FlutterStandardTypedData
的 data
属性时,出现以下异常:
'NSInvalidArgumentException',原因:'-[__NSArrayI 数据]: 无法识别的选择器发送到实例 0x7ff8f21ad000'
我不明白我收到此错误的原因,但我认为这是因为Uint8List
已放入 JSON 中,或者我正在尝试获取 @ 987654329@ 以错误的方式从字典中获取。反正我找不到解决办法。
我还尝试以另一种方式将 Uint8List
从 Flutter 传递给原生代码:在 Dart 中,我将 Uint8List
直接传递给原生代码(没有将其封装在 JSON 字符串中)。这样我就可以成功获取FlutterStandardTypedData
对象。这是另一个例子的代码。
飞镖代码:
await _channel.invokeMethod('testMethod',
dataBuffer, // example Uint8List
);
iOS 代码:
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result
if ([@"testMethod" isEqualToString:call.method])
FlutterStandardTypedData* dataBuffer = (FlutterStandardTypedData*)call.arguments[@"dataBuffer"];
但是我需要通过 JSON 字符串传递 Uint8List
。
如何将 Uint8List
从 Flutter 传递到 ios 原生,并将其封装在 JSON 字符串中?
【问题讨论】:
您想在 JSON 中包装字节的原因是什么?如您所见,正确的做法是直接传递。 在我的应用程序中,我调用了一个本地方法,传入一个存储“Uint8List”和其他属性的对象。为了将此对象传递给本机代码,我必须将其转换为 JSON 字符串。 字节数组并没有真正的 JSON 表示。它处理数字、字符串、布尔值等。您的 API 如何希望以 JSON 表示的字节数组? 我不知道,但在 android 本机代码中,我可以使用 Gson 成功地将 JSON 字符串(包含Uint8List
)转换为 Java 对象。在 Java 中,我将 Uint8List
转换为 byte[]
。
如果您在本机端将 JSON 解码回其组成部分,那么中间 JSON 形式的意义何在?只需将 Map<String, dynamic>
传递到 Dart-native 边界即可。映射的每个成员都可以是不同的(支持的)类型,例如字符串、布尔值、整数、浮点数、字节数组等。
【参考方案1】:
我猜你想要做的是在 Dart-native 边界上传递多个“参数”。为此使用Map<String, dynamic>
。例如:
await _channel.invokeMethod('testMethod', <String, dynamic>
'bytes': dataBuffer, // example Uint8List
'someBool': true,
'someInt': 123,
);
在本机端,您将获得一个映射或字典,其中包含作为键的键名和作为其本机等效项的值(例如 bool
->Boolean
等)
【讨论】:
感谢您的回答。我不能完全做到这一点,但我可以尝试将另一个Map
(包含dataBuffer
,这次不转换为字符串)作为Map
的参数传递给invokeMethod
。
非常感谢!我做了我之前评论中所说的,它解决了我的问题。而不是将 JSON 转换为字符串并将其作为 Map
传递给 invokeMethod
,然后在 iOS 中我将其作为普通的 NSDictionary
访问。【参考方案2】:
Objective-C 没有任何编译时类型安全工具,并将该责任留给开发人员。这里的异常表示您尝试使用数组对象,就好像它是 FlutterStandardTypedData 对象一样。但在运行时似乎并非如此。
我不知道 Dart 是如何将 Uint8List 序列化为 json,但查看异常,它看起来像是“[3,5,7]”。在 Objective-C 中反序列化它,你会得到一个整数数组,而不是 FlutterStandardTypedData。数组中的项目可能是 FlutterStandardTypedData 类型。
【讨论】:
那么,如何从 JSON 字符串中获取“‘‘FlutterStandardTypedData‘‘’?我是否应该将“dataBuffer”提取为一个整数数组,然后从该数组中创建一个“FlutterStandardTypedData”? 我不知道 Flutter 以及 FlutterStandardTypedData 的作用,但在 Objective-C 方面考虑,您需要将 json 反序列化为一个数组,并且该数组的每个成员都将是一个 int/float(或NS 编号)。只需在您的代码中放置一个断点并检查您在数组中的值的类型。 我试图从字典中提取数组作为NSArray
,将其转换为NSData
对象,然后转换为FlutterStandardTypedData
对象,但我无法访问缓冲区,所以我认为在这个过程中有些东西被破坏了。
不要将 NSArray 转换为 NSData。只需像 arr[0] 这样访问数组的成员,您就会在那里找到一个 int 或一个 NSNumber。
谢谢@Srdr,但我用 Richard Heap 的回答解决了我的问题。请看他回答下的cmets。以上是关于从字典访问 FlutterStandardTypedData 时出现“[__NSArrayI 数据]:无法识别的选择器”的主要内容,如果未能解决你的问题,请参考以下文章
从 Parse 访问字典数据并在 Tableview Cell 上显示
尝试从 Pandas DataFrame 中的字典访问第一个值时出现浮点错误