当前位置: > > > Swift - .plist文件数据的读取和存储

Swift - .plist文件数据的读取和存储

(本文代码已升级到Swift4)

每次在Xcode中新建一个iOS项目后,都会自己产生一个.plist文件,里面记录项目的一些配置信息。我们也可以自己创建.plist文件来进行数据的存储和读取。
 
.plist文件其实就是一个XML格式的文件,其支持的数据类型有(NS省略)Dictionary、Array、Boolean、Data、Date、Number、String这些类型。
当然对于用户自定义的对象,通过NSCoder转换后也是可以进行存储的。(常见我的另一篇文章“Swift - 本地数据的保存与加载(使用NSCoder将对象保存到.plist文件)”)

本文主要介绍如何使用.plist文件进行数组,字典,字符串等这些基本数据类型的存储和读取。
由于不需要转化,所以用起来还是很方便的。而且在大多数情况下,使用基本数据类型就足够了。

1,数组(Array)的存储和读取
(1)存储
下面把一个数组写入plist文件中(保存在用户文档目录),数组内是各个网站的地址。
let array = NSArray(objects: "hangge.com","baidu.com","google.com","163.com","qq.com")
let filePath:String = NSHomeDirectory() + "/Documents/webs.plist"
array.write(toFile: filePath, atomically: true)
进入目录打开webs.plist,可以看到生成的数据如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
	<string>hangge.com</string>
	<string>baidu.com</string>
	<string>google.com</string>
	<string>163.com</string>
	<string>qq.com</string>
</array>
</plist>

(2)读取
下面把webs.plist文件中数据读取出来显示在表格里
import UIKit

class ViewController: UIViewController , UITableViewDelegate, UITableViewDataSource{
    
    
    @IBOutlet weak var tableView: UITableView!
    
    var webs:NSArray?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        webs = NSArray(contentsOfFile: NSHomeDirectory() + "/Documents/webs.plist")
        self.tableView!.delegate = self
        self.tableView!.dataSource = self
        //创建一个重用的单元格
        self.tableView!.register(UITableViewCell.self, forCellReuseIdentifier: "cell0")
    }
    
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return webs!.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
        -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell0",
                                                 for: indexPath) as UITableViewCell
            let url = webs![indexPath.row] as! String
            cell.textLabel?.text = url
            return cell
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

2,字典(Dictionary)的存储和读取 
下面给每条网址都附上网站名,这时我们就要使用字典了。
(1)存储
除了每条网站记录使用字典类型,外面还拆分成两个数组分别存储,用于下面表格的分区展示。
let myArray = [
    [
        ["name":"航歌", "url":"hangge.com"],
        ["name":"百度", "url":"baidu.com"],
        ["name":"google", "url":"google.com"]
    ],
    [
        ["name":"163", "url":"163.com"],
        ["name":"QQ", "url":"qq.com"]
    ]
]  //声明一个字典

let filePath:String = NSHomeDirectory() + "/Documents/webs.plist"
NSArray(array: myArray).write(toFile: filePath, atomically: true)
print(filePath)
进入目录打开webs.plist,可以看到生成的数据如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
	<array>
		<dict>
			<key>name</key>
			<string>航歌</string>
			<key>url</key>
			<string>hangge.com</string>
		</dict>
		<dict>
			<key>name</key>
			<string>百度</string>
			<key>url</key>
			<string>baidu.com</string>
		</dict>
		<dict>
			<key>name</key>
			<string>google</string>
			<key>url</key>
			<string>google.com</string>
		</dict>
	</array>
	<array>
		<dict>
			<key>name</key>
			<string>163</string>
			<key>url</key>
			<string>163.com</string>
		</dict>
		<dict>
			<key>name</key>
			<string>QQ</string>
			<key>url</key>
			<string>qq.com</string>
		</dict>
	</array>
</array>
</plist>
(2)读取
下面把webs.plist文件中数据读取出来,并在表格里分区显示
import UIKit

class ViewController: UIViewController , UITableViewDelegate, UITableViewDataSource{
    
    @IBOutlet weak var tableView: UITableView!
    
    var webs:NSArray?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        webs = NSArray(contentsOfFile: NSHomeDirectory() + "/Documents/webs.plist")
        self.tableView!.delegate = self
        self.tableView!.dataSource = self
        //创建一个重用的单元格
        self.tableView!.register(UITableViewCell.self, forCellReuseIdentifier: "cell0")
        
    }
    
    // UITableViewDataSource协议中的方法,该方法的返回值决定指定分区的头部
    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return " ";
    }
    
    //在本例中,有2个分区
    func numberOfSections(in tableView: UITableView) -> Int {
        return webs!.count;
    }
    
    //每个分区的记录数
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        let data = self.webs?[section] as! Array<AnyObject>
        return data.count
    }
    
    //每个单元格创建和内容赋值
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
        -> UITableViewCell {
            let cell = UITableViewCell(style: .value1, reuseIdentifier: "cell0")
            let data = self.webs?[indexPath.section] as! Array<AnyObject>
            let url = data[indexPath.row]["url"] as! String
            let name = data[indexPath.row]["name"] as! String
            cell.textLabel?.text = name
            cell.detailTextLabel?.text = url
            return cell
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}
评论11
  • 11楼
    2017-11-12 03:28
    AlexLLL

    航哥我是小白,用你的代码,为什么初始化cell出错呢?,后续输出我也不大会……
    ===============
    import UIKit
    class _InformationTableViewController: UITableViewController {
    @IBOutlet weak var tableview: UITableView!
    ...

    站长回复

    看了下你的父类是UITableViewController,结果内部又加了个UITableView,这样自然会出问题。建议像我文章一样,父类实用UIViewController。
    如果非要用UITableViewController的话,可以学习下UITableViewController的用法,具体可以在网站的右上角搜索。

  • 10楼
    2017-09-16 22:55
    Jim

    你的第二个数组代码最后plist文件都没在路径里面出现,是有问题的。第一个案例没问题

    站长回复

    两个样例都是有加载plist文件啊?都在第12行。

    webs = NSArray(contentsOfFile: NSHomeDirectory() + "/Documents/webs.plist")

  • 9楼
    2017-08-09 11:03
    swift完善中

    请问航哥能不能给一份代码,邮箱434806909@qq.com,谢谢了

    站长回复

    本地的工程项目我也没有了,不过所有代码都在文章里,你创建个项目把代码粘贴进去即可。

  • 8楼
    2017-07-28 17:28
    助跑中的菜鸟

    请问航哥能不能出一篇关于如何生成、读写xml的文章,找了一圈也没有找到航哥这样风格的介绍

    站长回复

    我之前写过操作xml的相关文章,你可以看下:Swift - 解析XML格式数据(分别使用GDataXML和KissXML)

  • 7楼
    2017-02-22 16:10
    水淀粉

    你好writoFile在swift3.0已经不能用了,该怎么解决

    站长回复

    我已经把代码更新成Swift3的了,你可以再看看。

  • 6楼
    2016-06-13 14:49
    does_n

    怎么将新的数据覆盖旧的数据

    站长回复

    直接写文件就好了(writeToFile),新数据会自动覆盖旧数据。

  • 5楼
    2016-05-15 17:27
    xin

    您好我想把数据添加要已存在的plist中,我是先读去了plist文件并赋值给了一个数组,然后将我想添加的数据插入到数组中,然后再把数组写入plist文件中,打印plist文件内容显示添加成功了,但是打开plist文件里面没有我新添加的数据啊。怎么解决?

    站长回复

    先确认下你刚开始那个已存在的plist文件在哪里,如果是在app资源包中的plist文件。我们只能读取,不能写入。

    要保存的话,需要将其再保存到Documents文件夹下。如果要查看也要到这个app的Documents 文件夹下看。

  • 4楼
    2016-04-27 16:40
    van

    航哥,请问怎样才能想数据库添加数据一样,把添加页面输入的数据添加到plist中?

    站长回复

    plist不像数据库一样可以单独地新增或修改一条数据。通常都是将plist里的数据读取到数组或字典中,然后对数组或字典进行添加,删除等操作,操作完毕后再将所有数据重新覆盖写入到plist文件中。

  • 3楼
    2016-04-27 15:37
    van

    航哥,请问关于删除这个功能应该怎么写?

    站长回复

    将plist里的数据读取到数组或字典中,然后对数组或字典进行添加,删除等操作,操作完毕后再将所有数据重新覆盖写入到plist文件中。

  • 2楼
    2016-03-20 21:17

    多谢航哥!

    站长回复

    不客气,欢迎常来看看。

  • 1楼
    2016-01-12 14:44
    hahaxo

    nice~

    站长回复

    ^_^