我们写的导入方法,需要提示用户错误信息,我们用NSAlert
提示用户。新建一个类OAlertMessage
。
/// 提示错误信息
///
/// - Parameter message: 错误信息的文本
class func alert(message:String) {
let alert = NSAlert()
alert.messageText = message
alert.runModal()
}
因为要展示给用户一些异常的提示信息,我们修改之前代码把之前错误改成有提示的。
enum OFileMagerImportError:Error {
case cannel //点击了取消的按钮
case error(message:String)
}
修改之前的读取配置的方法改成下面的代码。
/*
* 导入配置文件
* return 返回一个数组对象 可能返回为空
*/
class func importAction() throws -> [Any]? {
let openPannel = NSOpenPanel()
openPannel.allowedFileTypes = ["ork"]; // 只允许读取.ork的文件类型
openPannel.allowsMultipleSelection = false // 设置不允许多选
let buttonIndex = openPannel.runModal()
guard buttonIndex == NSFileHandlingPanelOKButton else {
throw OFileMagerImportError.cannel
}
guard openPannel.urls.count > 0 else {
throw OFileMagerImportError.error(message:"你还没有选择任何的配置文件!")
}
guard let fileName = openPannel.urls.first else {
throw OFileMagerImportError.error(message:"你还没有选择任何的配置文件!")
}
guard let jsonData = try? Data(contentsOf: fileName) else {
throw OFileMagerImportError.error(message:"读取文件内容失败!")
}
guard let jsonObj = try? JSONSerialization.jsonObject(with: jsonData, options: .allowFragments) else {
throw OFileMagerImportError.error(message:"配置文件内容不是一个JSON文本!")
}
guard let configList:[Any] = jsonObj as? [Any] else {
throw OFileMagerImportError.error(message:"配置文件内容不是一个数组对象!")
}
return configList
}
这样抛出的异常信息我们就提示给用户到底是什么原因导致失败的。
@IBAction func importAction(_ sender: Any) {
do {
let configList:[Any] = try OFileManger.importAction()
print(configList)
} catch OFileMagerImportError.error(let message) {
OAlertMessage.alert(message: message)
}catch {
print("抛出了其他不给用户看到的错误!")
}
}
因为之前我们只是创建了测试的文件,里面是没有任何的东西的。所以会正常的提示配置文件的内容不是一个JSON文本
。
现在导入
的功能算是基本上写完了,我们继续写导出
的功能。
/// 导出配置到文件
class func exportAction() {
}
我们利用NSSavePannel
进行保存东西。
let savePannel = NSSavePanel()
savePannel.runModal()
我们在导出功能执行这个方法,看一下效果。
看样子和我们用到其他软件十分的相似了。
我们存的时候需要一个数组对象,我们按照打开的逻辑做一些异常处理。
savePannel.allowedFileTypes = ["ork"];
我们设置这个函数,强行让保存的文件是.ork
结尾的文件。因为上面也是这个名称,我们可以提炼成一个不可变的变量替换成用变量标识。
/// 导出配置到文件
class func exportAction(configList:[Any]) throws {
let savePannel = NSSavePanel()
savePannel.allowedFileTypes = [OFileImportExportTypeName];
let buttonIndex = savePannel.runModal()
guard buttonIndex == NSFileHandlingPanelOKButton else {
throw OFileMangerExportError.cannel
}
guard let filePath = savePannel.url else {
throw OFileMangerExportError.error(message: "保存文件名称不能为空!")
}
guard let jsonData = try? JSONSerialization.data(withJSONObject: configList, options: .prettyPrinted) else {
throw OFileMangerExportError.error(message: "配置的数组对象无法转换为JSON对象")
}
do {
try jsonData.write(to: filePath)
} catch _ {
throw OFileMangerExportError.error(message: "导出文件失败!")
}
}
enum OFileMangerExportError:Error {
case cannel
case error(message:String)
}
我们已经做好了导入
和导出
的功能,现在我们给ViewController
新增加一个属性configList
接受我们导入的配置数组。
/// 配置的数组对象
var configList:[Any]?
我们写一个didSet
方法,让表格自动的刷新。
/// 配置的数组对象
var configList:[Any]?{
didSet {
reloadTableView()
}
}
func reloadTableView() {
}
在AppDelegate
里面新增加一个方法refershViewControllerList
去设置主界面的数据源。
/// 刷新主界面的列表
///
/// - Parameter list: 从文件读取的配置列表
func refershViewControllerList(list:[Any]) {
guard let window = NSApp.windows.first else {
return
}
guard let controller = window.contentViewController else {
return
}
guard let vc = controller as? ViewController else {
return
}
vc.configList = list
}
新建一个类OHomeCellView
继承NSTableCellView
。
mac开发中使用自定义NSTableCellView
我们实现NSTableView
的代理,先设置3
条测试的数据。
我们自定义的NSTableCellView
的类
class OHomeCellView: NSTableCellView {
/// 显示配置的名称
@IBOutlet weak var configNameLabel: NSTextField!
/// 显示是否勾选了这个配置
@IBOutlet weak var configCheckBox: NSButton!
override func draw(_ dirtyRect: NSRect) {
super.draw(dirtyRect)
}
}
我们注册我们的cell
//FIXME: - NSTableViewDataSource
public func numberOfRows(in tableView: NSTableView) -> Int {
return 3
}
public func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
let view = tableView.make(withIdentifier: "OHomeCellView", owner: self)
guard let cell = view as? OHomeCellView else {
return nil
}
cell.configNameLabel.stringValue = "这是测试的数据"
cell.configCheckBox.state = 0
return cell
}
func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
return 40
}
最后显示的效果
代码下载