iOS - 来自 NSData 完成处理程序的 writeToFile

Posted

技术标签:

【中文标题】iOS - 来自 NSData 完成处理程序的 writeToFile【英文标题】:iOS - writeToFile from NSData completion handler 【发布时间】:2018-02-23 16:05:22 【问题描述】:

我正在从 web 服务获取文件的字节,我的目标是获取这些字节,将它们放入 NSData,然后写入文件,一旦 writeToFile 完成 100%,我将显示文件(它是PDF,最多可以有 6 页)在 QLPreviewController 中。

我能够从 web 服务中获取字节并将它们放入 NSData,如下所示:

NSArray *byteArray = [dataSource.areaData GetPDFFileData:[NSString stringWithFormat:@"%@",encodedUrlStr]];

        NSData *data;

        for (NSDictionary *dict in byteArray) 
            NSString *base64 = dict[@"data"];
            data = [[NSData alloc] initWithBase64EncodedString:base64 options:0];
        

现在我正在尝试这样编写文件:

if (data)
        
            NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
            NSString *documentsDirectory = [paths objectAtIndex:0];

            filePath = [NSString stringWithFormat:@"%@/%@", documentsDirectory,PDFFile];

            [data writeToFile:filePath atomically:YES];

        

现在我要做的是拥有某种完成处理程序,因此在文件完全写入之前不会发生任何其他事情。最好的方法是什么?

我也开始研究 NSFileHandle,那会是更好的解决方案吗?

【问题讨论】:

【参考方案1】:

使用 NSFilePresenter 来监控文件的变化 并使用 NSFileCoordinator 写入它

在模拟代码中:

NSFilePresenter *p = [NSFilePresenter presenterWithFile:f];
[p signupForChangeNotificationsOrSetDelegateOrWhatever....];

//write 
NSFileCoordinator *c = [NSFileCoordinator coordinatorWithPresenter:p];
[c coordinate writeData....]

... called back by p cause we changed

【讨论】:

什么是 FVEvents? 抱歉,这是 FSEvents。错字。但无论如何它并不理想 - 你想要一个 NSFileCoordinator 你能提供一个NSFileCoordinator的例子吗? 稍微更新一下我的代码。这个模拟来自阅读 api。我在黑暗的过去使用过 FSEvents。不过,这应该可以帮助您入门。 我不断收到此错误,是的,我确实导入了 Foundation Use of undeclared identifier 'NSFilePresenter'【参考方案2】:

如果在主队列中运行它是串行的,则无需担心完成,但最好保存在后台队列中并读取内容以验证并呈现在主队列中

  DispatchQueue.global(qos: .background).async 
        print("This is run on the background queue")

        if (![[NSFileManager defaultManager] fileExistsAtPath:filePath])
        
            NSLog(@"not exists");

            NSData *fileContents = [@"" dataUsingEncoding:NSUTF8StringEncoding];
            [[NSFileManager defaultManager] createFileAtPath:filePath
                                                    contents:fileContents
                                                  attributes:nil];

        
        else
        
             NSLog(@"exists");

        


        NSFileHandle *myHandle = [NSFileHandle fileHandleForWritingAtPath:filePath];
        [myHandle seekToEndOfFile];


        NSString*strTowrite=[NSString stringWithFormat:@"%@ || %@ --- %@ \r\n",dt,acion,name];

        [myHandle writeabilityHandler];

        [myHandle writeData:[strTowrite dataUsingEncoding:NSUTF8StringEncoding]];


    DispatchQueue.main.async 
        NSString*content=[[NSString alloc] initWithContentsOfFile:filePath
                                                         encoding:NSUTF8StringEncoding
                                                            error:&error];
         if(content)
        


            NSLog(@"content is : %@ Err : %@",content,error);

            // [self sendfile];


        
        else
        

            NSLog(@"Failed to store the file. Error = %@", error);

        
     
    

【讨论】:

我不明白这一行: NSString*strTowrite=[NSString stringWithFormat:@"%@ || %@ --- %@ \r\n",dt,acion,name];什么是 dt....什么是行动....什么是名称?在我的情况下他们会是什么 这是你想要保存的任何东西我的意思是任何字符串 我觉得这是 hacky,如果它甚至可以工作.. 它工作得很好,因为 IO 将被序列化,所以在阅读之前发生写入但是......不知道.. 似乎开销。想象一下你写/复制/移动 200MB。你真的想把它全部读回来吗:D @Daij-Djan ,当然不想读回来,我这样写是为了验证写入步骤成功发生,而且我认为写入过程不会那么大 200 MB写在移动应用程序中的大小太可怕了

以上是关于iOS - 来自 NSData 完成处理程序的 writeToFile的主要内容,如果未能解决你的问题,请参考以下文章

如何从NSURLSessionDataTask完成处理程序返回NSData

在 iOS 应用程序中处理数据(选择啥?NSData、CoreData、sqlite、PList、NSUserDefaults)

IO 直接播放来自 UDP 流 (NSData) 的原始音频

IOS:从照片路径获取 NSData

如何使用来自iPhone应用程序的SOAP请求将图像+ xml上传到Web服务器

Swift 中的完成处理程序错误