有什么方法能把txt文件转为数组数据_用Swift开发macOS程序,七、文件模块

a858de6779150615bdfefc879b6d065d.png
这是我们第一次写较多代码。当我们写过一些代码,我们就知道,写文档往往比写代码更复杂更费时间。这也是我们看到很多程序没有文档、文档不全和文档不祥的原因。但是一个程序如果没有文档,就无法好好的继承、好好的被使用,所以文档是必须的。程序文档有很多种,但对于我们开发人员来说,有功能说明、业务流程、数据结构等就可以了。但当我们写好文档,回头一看程序又变了,看怎么办,得把文档找出来再改呗。如此反覆,烦不胜烦,大部分程序员是这样死掉的。那怎么办,许多程序员使用的是折中的方法是:先把程序里的注释写得尽量详细再说,免得一回头,自己都不知道以前在干嘛,哈哈,我们也先这样。首先,一个类的头部注释是说明这个类能够干什么,要写细哟;然后,各属与方法也得写清楚;但不要以为这样就完了,你还有N多东西要说明,这些放在哪里我就不知道了,所以最后,我们还是需要补上文档。
另外,动手之前,我们还需要熟悉一下Swift 编码规范。

文件模块是我们需要攻下的第一个城池。它有文件读写功能,解压与压缩功能,数组、字典与数据模型互转功能,JSON编码与解码功能。这些功能是一个个碉堡,我们要逐个击破,然后一举拿下城池。最后,积兵储粮,继续挥帜北上,去完成我们的春秋霸业。

〜〜〜〜〜 概述 〜〜〜〜〜

基于“iWriter”设计,我们需要保存作品信息(info.txt)、作品目录(catalog.txt)、作品角色(role.txt)、作品符号(symbol.txt)、章节正文(chapter章节ID.txt)、正文的备注(note备注ID.txt)等数据内容。其中前四者为随新建文件时建立存储文件,后两者由使用者在作业过程中创建。
  • 功能及流程。文件模块有新建文件、打开文件、保存文件、另存文件等一系列跟文件操作有关的功能。下面就主要功能作流程说明如下:

新建文件:

  1. 获取用户指定的保存位置path及文件file;
  2. 在缓存区清空或新建临时文件夹iwriter;
  3. 在iwriter文件夹内新建文件info.txt、catalog.txt、role.txt、symbol.txt;
  4. 为info.txt写入初始内容;
  5. 将iwriter压缩到用户指定位置path,并命名为file;
  6. 完成整个新建文件过程。

打开文件:

  1. 获取用户指定打开的文件file(含位置path);
  2. 在缓存区清空或新建临时文件夹iwriter;
  3. 将file解压到缓存区iwriter。注意,本程序只保持一份缓存,也就是说只能打开一个编辑实例;
  4. 在iwriter打开Works,即加载其数据;
  5. 完成整个打开文件流程。

保存文件:

  1. 保存Works数据到缓存区iWriter的各文件里;
  2. 将缓存区iwriter打包,覆盖到用户指定的保存位置path,覆盖其文件file。
  3. 完成整个保存文件流程

另存文件:

  1. 重新获取用户指定的保存位置path及文件file;
  2. 保存Works数据到缓存区iWriter的各文件里;
  3. 将缓存区iwriter打包,覆盖到用户指定的保存位置path,覆盖其文件file。
  4. 完成整个另存文件流程
  • 单元测试。单元测试是针对程序模块进行的正确性检验的工作,以保证其正确性与健壮性。单元测试在开发中极为重要,是程序质量的重要保证。一般程序开发中会使用PDCA来管理其质量,我们大多会以模块为输出节点,在进行PDCA时,单元测试是其Check部分。

下面我们从数据逻辑与业务逻辑两个方面来实现文件模块的功能。并通过单元测试Check我们的输出是否符合我们的设计要求。

〜〜〜〜〜 正文 〜〜〜〜〜

到这里,单靠以前我们所学的Swift基本知识还是远远不够的。我们还需要跟据我们实现的功能去查找并了解一些类与库,一般使用Google搜索与看文档是我的主要方法。对于我们一个新手来说:首先,要做一个“搜索程序员”;然后,再去做一个“文档工程师”。

我预计了一下,文件模块所用的类与库有这些:

  1. NSOpenPanel,显示窗口,供用户选择打开的文件;
  2. NSSavePanel,显示窗口,供用户选择文件保存位置与设置文件保存名称。
  3. FileManager,文件操作。
  4. String、Data、JSON类,方便将数据写入到文件或从文件里读出来,还有是跟数据模型间的转换。
  5. ZipArchive库,第三方提供的zip压缩与解压功能的库,所以我们这里会涉及到第三方库管理的问题。

第三方库管理:大家都用CocoaPods管理第三方库,这应该是个非常好用的工具,但是由于某些原因实际上非常不好用。如想使用它,请参考墨彻的CocoaPods详细安装及使用教程。

一、配置程序对系统权限。

在开发文件模块之前,需要为应用程序开启对本地资源应用的权限。请按下列步骤操作:其中第5步是获取打印权限,后续会用到;第6步是获取用户选择的文件夹的读写权限,另外,还有获取下载文件夹的读写权限,下载文件夹的读写权限是为了下面的单元测试用,“iWriter”中用不着,后期会关闭。

2b9100311e00679564cf35d26ae96b74.png
  • 添加第三方库。
以ZipArchive为例,点击打开Github相应页面,选择右边“Clone or download”的绿色按钮,在下拉项里点击“Download Zip”,等待下载完成后,请解压备用。

下面是说说自己管理与应用第三方库:

  1. 在Navigator Area里选择Subject栏的Venders项,点击右键。然后选择右键菜单中的‘Add Files to “iWriter”...’项;
  2. 在打开的文件流览器中,找到备用处,选择“ZipArchive.xcodeproj”,确认添加;
  3. 将“ZipArchive.framework”添加各”TARGETS“的第三方链接库:
    1. 在Navigator Area的Subject栏里,选择第一个“iWriter”后,再选择Editor Area的”TARGETS“中的”iWriter“项,同时选择上方水平栏“Build Phases”项;
    2. 在页面中的“Link Binary With Libraries”栏里,点击其下面的“+”,跳出的framework流览窗口,请选择“ZipArchive.framework”,注意选择带“mac”那项,确认添加“ZipArchive.framework”。
    3. 按该方法,请为”TARGETS“的”iWriterTests“和”iWriterUITests“,同样添加“ZipArchive.framework”。

6c07f4b3da4b9a04833d478288e5d1ea.png

e8e7b9463dd66f478133b93d203da2a2.png

f3869dc156b9f3e1851487be9177526b.png

使用CocoaPods管理与应用第三库:

  1. 如果没有网络问题,CocoaPods管理与应用第三库非常简单。在安装好CocoaPods后,我们需要准一个Podfile的文件,并放在工程根目录下;
  2. 在文件里写上我们需要的第三方库(请确认该库是否支持CocoaPods),并设置是否用在主工程、单元测试工程、UI测试工程等;
  3. 在Terminal里,进入到工程根目录,运行:$ pod install,如果运行成功就完成了;
  4. 如果想移除某第三方库,在Podfile文件里,使用“#”符注释掉该行,然后再在Terminal里,进入到工程根目录,运行:$ pod instal,如果运行成功就移除完成了。
  • Podfile文件:
source 'https://github.com/CocoaPods/Specs.git'

#inhibit_all_warnings!
platform :macOS, '10.14'
set_arc_compatibility_flag!

def import_pods
  pod 'SSZipArchive'
end

target :iWriter do
  import_pods
end

target :iWriterTests do
  import_pods
end

target :iWriterUITests do
  import_pods
end

二、数据模型与数据逻辑支持。

我们为“iWriter”设计了四种数据模型,分别是:Info、Catalog、Role、Symbol。要说明的是这些数据完全可以使用Array、Dictionary代替,而且还简单。我也不知道为什么要这么做?为了MVC模式?MVP?MVVM?不知道。同时为了好让这些数据模型转为Array、Dictionary,我们又设计了一个"WorksDelegate"协议。最后又为了数据的更新我们设计了一个“Status”。
  • 建立Struct,步骤如下,后续章节不再讲:
  1. 按住“command+N”,在“Choose a template for you new file”窗口中选择菜单“macOS”,在“Source”栏选择“Swift File”项,确定“Next”;
  2. 在文件流利器中,选择“Models”文件夹,输入文件名称,确定“Creat”,完成Struct文件的创建。
  • WorksDelegate协议,Models文件夹下WorksDelegate.swift。
import 
  • Info、catalog、role、symbol等数据模型,Models文件夹下对应Info.swift、catalog.txt、role.txt、symbol.txt等文件。
数据模型的实现方式一样。
其中catalog有属性level: Int、title: String、info: String、creation: Int、number: Int,
而role与symbol有属性name: String、info: String、creation: Int。
import 
  • Status结构体,Models文件夹下的Status.swift。
保存最近Works数据的MD5,判断基于新数据是否需要保存。
import 

三、数据逻辑与业务逻辑的实现。

逻辑的实现分三部分:首先,建立菜单项的Action,也就是要有监听与处理用户操作行为的方法;其次,实现Action,也是业务逻辑部分,同时需要为部分操作提供后续用户交互;最后,处理Action所产生数据及保存问题,即数据逻辑部分。
  • 建立Action。
文件模块是支持与实现菜单操作,所以需要为对应的菜单项建立建立Action。本例将最后一次讲述如何创建Action,后面所有章节中不再讲述其操作流程。
  1. 将Editor Area切换到Assistant模式,左为Main.storyboard,右为AppDelegate.swift;
  2. 选其中一菜单项,按住“control”,拖菜单项到右边类主体的方法区,在跳出窗口中设置Action方法;
  3. 所有Action建好后,将其划分为extension里,以便于管理与查看。

80a20f3cd9acda8c0a1161c41bf5c885.png
  • 实现业务逻辑,所有代码均在AppDelegate.swift。
文件模块中打开文件、新建文件、别存文件涉及到了文件浏览器窗口,对应Swift分别需要NSOpenPanel与NSSavePanel类的支持。其中新建文件、另存文件调用的是NSSavePanel类。
// 
其中openFile()、newFile()、saveAsFile()需要打开文件流览器,让用户选择或设置文件(含路径),以传给数据逻辑进行处理,而saveFile()直接启动数据逻辑处理。由于涉及到文件操作与JSON数据转换,所有以数据逻辑在处理旱均会抛出异常。我们需要接收并处理异常,本案的方法是将异常中的错误信息输出(后期输出到log),话术信息则显现给用户。
// 
  • 实现数据逻辑,所有代码均在Works.swift。
Works.swift的主要内容是Works类。创建Class文件时,需要按创建Struct文件的步骤,只是在第一步中不选择“Swift File”,而选择“Cocoa Class”。我在实现Works类之前,还需要定义两个枚举,一个WorksError用来处理异常,一个OperateCode用来表明引起异常的原因。
/**

这里我们使用了带参数的枚举,以便将出错的信息传递出去。

Works类。公共部分,是映射Action,并按业务流程处理数据;私有部分,处理数据文件的读写;其余的,提供额外支持。其中,文件读取没有使用FileHandle,因为每次数据更新写入之后需要压缩为“.iw”文件,造成反复打开关闭FileHandle,比较麻烦。
/**

四、单元测试。

单元测试所做的事情,我们以前靠Print与断点调试来解决,现在当然还在用。我们之所以需要使用单元测试,更多的原因有三点:首先,单元测试可以使用更小单位,这意味着测试更加便捷与有效;其次,单元测试有更灵活的输入,这意味着我们不仅可输入即定数据,还可以输入脏数据,以检验程序的正确性与可靠性;最后,单元测试有更完备的输出验证手段。
写本章时,因为建立与完成单元测试,耽误了一整天的时间。Xcode在第三方库管理与应用上并不复杂,我们按上面所说的做就行了。但我在Works类测试时,一直出现测试失败,于是各种找方案、各种修改“.iw”保存文件夹的权限,都行不通。最后,原来是测试时预定的“.iw”保存路径的有问题,由于不是用户选择、也不是在App Sendbox里,所以没有作何操作权限。这也是为什么一开始,我们需要在App Sendbox里为Downloads Folder添加读写权限的原因,测试时我们只能将“.iw”保存路径设置在Downloads Folder里。
  • 了解单元测试的结构。
由于我们新建“iWriter”工程时勾选了"Include Unit Tests"和"Include UI Tests"项,所以现在可以在Navigator Area的Test栏里,看到“iWriterTests”与“iWriterUITests”项。打开“iWriterTests”主件有如下四个方法:
import 
  • 数据模型的测试。
测试了数据模型与Dictionary的转换、接收脏数据是否符合预期,下面以Info为例。
/// 测试Info数据模型
    
  • 数据逻辑的测试。
基于操作进行了测试,操作有新建、保存、另存、打开。
  1. 新建,断言缓存区默认的文件是否创建,是否按用户指定路径创建文件;
  2. 保存,断言修改的数据是否保存,章节是否创建;
  3. 另存,断言是否按用户指定路径保存文件;
  4. 打开,断言章节内容是否相同,断言数据是否确。
/// 测试Works数据模型
    
  • “iWriter”原码,请访问我的Github的iWriter工程。

下一篇,布局模块的实现。

让我们在这里,遇见明天的自己!姜友华

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值