如何在 iOS 中使用 NSKeyedArchiver 将已写入文件系统的文件读取为 Flutter 中的字符串?
How to read file as String in Flutter that has been written to filesystem using NSKeyedArchiver in iOS?
更新 iOS 本机应用程序并在 Flutter 上编写应用程序后,我想从 [=] 上的文件系统读取文件=28=]iOS 设备使用 Dart。我要读取的文件之前已使用此 ObjectiveC
代码写入文件系统:
- (void)setAccount:(FTAccountModel *)account {
_account = account;
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
path = [path stringByAppendingPathComponent:AccountModelPath];
if (account) {
NSArray * array = @[account];
[array writeToFile:path atomically:YES];
[NSKeyedArchiver archiveRootObject:array toFile:path];
}
}
我在 Flutter 中使用 path_provider 包尝试了以下方法:
final appDocDir = await getApplicationDocumentsDirectory();
final accountDataFile = File('${appDocDir.path}/$_iosAccountDataFile');
String contents = await accountDataFile.readAsString();
print("contents: $contents");
但是调用readAsString()
方法时出现错误:
FileSystemException: Failed to decode data using encoding 'utf-8', path = '/var/mobile/Containers/Data/Application/FBCB4862-E5EA-4C93-8C2E-3DF1F00A8645/Documents/AccountModel.data'
如何使用 Dart
和 Flutter
读取 iOS 设备上使用 NSKeyedArchiver
写入的文件?
在撰写此答案时,没有用于读取文件的插件,该文件之前已使用 iOS 中的 NSKeyedArchiver
写入文件系统。读取文件的方式是write custom platform-specific code.
因此 Swift 上的 iOS 平台代码将类似于以下内容:
private func callGetUserIdFromNativeApp(result: @escaping FlutterResult) {
var account: FTAccountModel?
let fm = FileManager.default
let urls = fm.urls(for: .documentDirectory, in: .userDomainMask)
if (!urls.isEmpty) {
let file = urls[0].appendingPathComponent("Accounts.data", isDirectory: false)
if (fm.fileExists(atPath: file.path)) {
if let accountArray: [FTAccountModel] = NSKeyedUnarchiver.unarchiveObject(withFile: file.path) as? [FTAccountModel] {
if (!accountArray.isEmpty) {
account = accountArray[0]
}
}
}
}
if let userId: Int = account?.userId {
result(String(userId))
} else {
result(nil)
}
}
而flutter部分将使用MethodChannel
调用原生代码:
static const MethodChannel _channel = const MethodChannel("CHANNEL_NAME");
static Future<String> getUserIdFromNativeIos() async {
try {
return await _channel.invokeMethod("METHOD_NAME");
} catch (e){
return _failedString();
}
}
更新 iOS 本机应用程序并在 Flutter 上编写应用程序后,我想从 [=] 上的文件系统读取文件=28=]iOS 设备使用 Dart。我要读取的文件之前已使用此 ObjectiveC
代码写入文件系统:
- (void)setAccount:(FTAccountModel *)account {
_account = account;
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
path = [path stringByAppendingPathComponent:AccountModelPath];
if (account) {
NSArray * array = @[account];
[array writeToFile:path atomically:YES];
[NSKeyedArchiver archiveRootObject:array toFile:path];
}
}
我在 Flutter 中使用 path_provider 包尝试了以下方法:
final appDocDir = await getApplicationDocumentsDirectory();
final accountDataFile = File('${appDocDir.path}/$_iosAccountDataFile');
String contents = await accountDataFile.readAsString();
print("contents: $contents");
但是调用readAsString()
方法时出现错误:
FileSystemException: Failed to decode data using encoding 'utf-8', path = '/var/mobile/Containers/Data/Application/FBCB4862-E5EA-4C93-8C2E-3DF1F00A8645/Documents/AccountModel.data'
如何使用 Dart
和 Flutter
读取 iOS 设备上使用 NSKeyedArchiver
写入的文件?
在撰写此答案时,没有用于读取文件的插件,该文件之前已使用 iOS 中的 NSKeyedArchiver
写入文件系统。读取文件的方式是write custom platform-specific code.
因此 Swift 上的 iOS 平台代码将类似于以下内容:
private func callGetUserIdFromNativeApp(result: @escaping FlutterResult) {
var account: FTAccountModel?
let fm = FileManager.default
let urls = fm.urls(for: .documentDirectory, in: .userDomainMask)
if (!urls.isEmpty) {
let file = urls[0].appendingPathComponent("Accounts.data", isDirectory: false)
if (fm.fileExists(atPath: file.path)) {
if let accountArray: [FTAccountModel] = NSKeyedUnarchiver.unarchiveObject(withFile: file.path) as? [FTAccountModel] {
if (!accountArray.isEmpty) {
account = accountArray[0]
}
}
}
}
if let userId: Int = account?.userId {
result(String(userId))
} else {
result(nil)
}
}
而flutter部分将使用MethodChannel
调用原生代码:
static const MethodChannel _channel = const MethodChannel("CHANNEL_NAME");
static Future<String> getUserIdFromNativeIos() async {
try {
return await _channel.invokeMethod("METHOD_NAME");
} catch (e){
return _failedString();
}
}