如何在 iOS 中使用 NSKeyedArchiver 将已写入文件系统的 Flutter 中的文件作为字符串读取?

Posted

技术标签:

【中文标题】如何在 iOS 中使用 NSKeyedArchiver 将已写入文件系统的 Flutter 中的文件作为字符串读取?【英文标题】:How to read file as String in Flutter that has been written to filesystem using NSKeyedArchiver in iOS? 【发布时间】:2021-04-16 13:16:42 【问题描述】:

使用 Flutter 上编写的应用更新 iOS 本机应用后,我想使用 iOS 设备上的文件系统读取文件飞镖。我要读取的文件之前已使用此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'

如何在 iOS 设备上使用DartFlutter 读取使用NSKeyedArchiver 编写的文件?

【问题讨论】:

你找到解决问题的方法了吗,我也遇到了同样的问题 【参考方案1】:

在撰写此答案时,没有插件可以读取该文件,该文件之前已在 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 中使用 NSKeyedArchiver 将已写入文件系统的 Flutter 中的文件作为字符串读取?的主要内容,如果未能解决你的问题,请参考以下文章

iOS - 如何使用 branch.io 在 Appstore 中测试深度链接

如何在 iOS 6 中使用 NSLayoutConstraint?

如何在 iOS 8 中使用带有 NSNotificationCenter 的小部件

如何在ios5中使用identifierForVendor。?

如何在 iOS 8 中使用 UIAlertView? [复制]

我应该如何在 iOS 7 中使用具有 iOS 6 风格的 UIButtons?