最近在开发iOS上的OTG,也就是从U盘中导入文件到App中,然后对此进行后续的操作。iOS13之后就支持了OTG,这个功能非常实用,无论是外接U盘,或者是录音笔,都可以很方便的导入各种你App内支持的格式。在这个开发过程中,遇到了很多问题,真的是一步一步踩坑踩过来的。因为iOS11 之后就支持应用内互相拷贝文件,只要给App添加权限就可以支持,这边不细说,网上很多资料。记录一下我在开发过程中遇到的问题。
我的需求是能将录音笔中音频的文件导入到App中,指定格式为WAV,MP3,M4A,在开发过程中使用的是UIDocumentPickerViewController, 使用很简单,初始化,设置代理就可以了。但是在进行文件过滤的时候出现了问题。文件过滤实际上是对非指定的格式的文件进行置灰,这块逻辑是系统定义好的,我们只能按照规则走。我查了网上的资料,都说 只要 let docVC = UIDocumentPickerViewController.init(documentTypes: "mp3", "wav", "m4a"], in: UIDocumentPickerMode.open)
上面的代码就能支持过滤了,但是我实践下来根本就不可行,我试了"MP3"这种大写的也还是不行,差不多试过了各种排列组合了。。。。都还是不行。后来去查了一下,上面的写法是错误的,要换成
let docVC = UIDocumentPickerViewController.init(documentTypes: [String(kUTTypeWaveformAudio), String(kUTTypeMP3), String(kUTTypeMPEG4Audio)], in: UIDocumentPickerMode.open)
这种写法才能实现过滤。Type的定义都在CoreServices中的UICoreTypes中,对于音频来说,还有好多格式都是没有的,比如ogg,所以如果要不过滤这种格式,可能要寻找其他的方案。
上面是开发过程中遇到的第一个坑,相对来说,这个坑还是比较简单的,处理方式也简单,接下来的问题就越来越头疼了。
在开发过程中需要区分导入的音频所属的设备。我查了很多资料,也实践了很多,得出的结论,没有办法直接拿到哪怕是外接U盘的名称。首先这里要说一下,UIDocumentPickerMode区分open和`import`模式的,这两个模式的区别网上也有很多,不做详细的解释了,如果是App之间的文件拷贝,一般都是使用的import,这个没有问题,因为按照我的理解,如果App之间文件共享,文件是会在一个公共的地方进行共享,这个动作很快,耗时很短,当你选择一个文件进行文件导入时,这个选择的文件路径是个虚拟路径,不是文件真正的路径,但是如果UIDocumentPickerMode改成open模式,这个时候文件导入的路径就是文件真正的路径,这个路径中包含U盘的名称,如果想要区分设备,只能去截取这个路径,拆解出U盘的名称,通过U盘名称去区分设备了。我暂时只发现了这个解决方案,如果又其他的解决方案,麻烦指导一下,感谢了。而且这边还有一个坑,如果是应用之间进行文件共享,import模式没有问题,但是如果是用来导入U盘中的文件,在 funcdocumentPicker(_controller:UIDocumentPickerViewController, didPickDocumentsAt urls: [URL])
这个代理方法中会直接卡死,无论是在代理中创建子线程去执行逻辑还是什么都不做,都会卡死,我猜测这个问题的原因是,使用import模式,系统会在选中的时候,将文件拷贝到系统的某个路径下,而且是占用的主线程,在没有拷贝完成之前整个App就会卡死,完全动不了。解决方案就是使用open模式,但是open模式需要在代理中创建一个子线程去做耗时的操作,比如拷贝,转码之类的,否则遇到耗时的操作还是会卡死。上面是我的猜测,如果有不对的地方麻烦指出来,感谢。
这篇文章先写这一个问题,后面还遇到好多坑,在接下来的文章中分享。