swift本地存储

前言:在我们开发过程中,不管是你做啥子应用,都要遇到数据的保存问题。将数据保存本地,这样让程序的运行更加流畅,不在出现小菊❀这样的╮(╯﹏╰)╭东东了,使得用户体验更好! 以下将介绍NSUserDefaults/ NSKeyedArchiver/ write写入方式.

文件操作知识临时充饥看我上篇文章:Swift文件管理必知的一些操作

1.使用NSUserDefaults存储数据

NSUserDefaults:一般我们拿它用来保存应用程序设置和属性、用户保存的数据,用户的手机不管是关机or开机时候都会保存在本地(除非你把他删除了),它一般可以存储类型包括:字符,数组,字典,NSData,NSNumber以及基本数据类型都可.那就来看看咋的实现它吧!
这里我简单的对其简单封装了一下方法,我就直接贴代码了,重要位置我都加了注释(ps:想看比较全面的可以参考这篇文章Swift之一步一步带你封装一个本地缓存库):

    /*  使用NSUserDefaults对普通数据对象储存   */

    /**
     储存

     - parameter key:   key
     - parameter value: value
     */
    class func setNormalDefault(key:String, value:AnyObject?){
        if value == nil {
            NSUserDefaults.standardUserDefaults().removeObjectForKey(key)
        }
        else{
            NSUserDefaults.standardUserDefaults().setObject(value, forKey: key)
            // 同步
            NSUserDefaults.standardUserDefaults().synchronize()
        }
    }

    /**
     通过对应的key移除储存

     - parameter key: 对应key
     */
    class func removeNormalUserDefault(key:String?){
        if key != nil {
            NSUserDefaults.standardUserDefaults().removeObjectForKey(key!)
            NSUserDefaults.standardUserDefaults().synchronize()
        }
    }

    /**
     通过key找到储存的value

     - parameter key: key

     - returns: AnyObject
     */
    class func getNormalDefult(key:String)->AnyObject?{
        return NSUserDefaults.standardUserDefaults().valueForKey(key)
    }

下面举个简单 looklook

private func userDefaultStoreData(){
        Tool.setNormalDefault("name", value: "Rookie")
        let value = Tool.getNormalDefult("name")
        print("测试NSUserDefaults 简单对象储存\\(value)")
    }

//   控制台输出: **测试****NSUserDefaults ****简单对象储存****Optional(Rookie)**

2.通过write写入方式存储为plist属性列表
write写入方式也是一种把数据永久保存在磁盘中储存方式,一般步骤:1)获取路径(一般有两种方式:使用NSSearchPathForDirectoriesInDomains或URLsForDirectory;使用NSHomeDirectory➕相应的路径);2)向文件中写入数据;3)从文件中读取数据. 具体代码如下:

    /**
     创建文件

     - parameter name:        文件名
     - parameter fileBaseUrl: url

     - returns: 文件路径
     */
   class func creatNewFiles(name:String, fileBaseUrl:NSURL) -> String{
        let manager = NSFileManager.defaultManager()
        let file = fileBaseUrl.URLByAppendingPathComponent(name)

        let exist = manager.fileExistsAtPath(file.path!)
        if !exist {
            let createFilesSuccess = manager.createFileAtPath(file.path!, contents: nil, attributes: nil)
            print("文件创建结果: \\(createFilesSuccess)")
        }
        return String(file)
    }

    /**
     读取文件

     - parameter name:        文件名
     - parameter fileBaseUrl: url

     - returns: 读取数据
     */
    class func readTheFlies(name:String , fileBaseUrl:NSURL) ->NSString{
        let file = fileBaseUrl.URLByAppendingPathComponent(name)
       //  print(file)
        let readHandler = try! NSFileHandle(forReadingFromURL:file)
        let data = readHandler.readDataToEndOfFile()
        let readString = NSString(data: data, encoding: NSUTF8StringEncoding)
        return readString!
    }

实现 如下:

// MARK:-  存储plist属性列表
    private func savePlistFiles(){
        // 储存的沙盒路径
        let manager = NSFileManager.defaultManager()
        let urlForCatch = manager.URLsForDirectory(NSSearchPathDirectory.CachesDirectory, inDomains: NSSearchPathDomainMask.UserDomainMask)
        let url = urlForCatch.first! as NSURL
        let fileName = "RookieSon.plist"
        // 创建文件
        let filesPath = Tool.creatNewFiles(fileName, fileBaseUrl: url)
        // 储存数据
        let saveDataInfo = NSMutableArray()
        saveDataInfo.addObject("我的剑,就是你的剑")
        saveDataInfo.addObject("我用双手成就你的梦想")
        saveDataInfo.addObject("纵然前路迷茫,纵然天隔一方,纵然我手中的刀刃已然破碎,也无法阻挡我寻找你的道路")
        //        print(saveDataInfo)
        // 写入文件
        saveDataInfo.writeToURL(NSURL(string: filesPath)!, atomically: true)

        // 读取文件
        let readDataInfo = Tool.readTheFlies(fileName, fileBaseUrl: url)
        print(readDataInfo)
    }

/* 打印结果: 
**<plist version="1.0">**
**<array>**
** <string>****我的剑****,****就是你的剑****</string>**
** <string>****我用双手成就你的梦想****</string>**
** <string>****纵然前路迷茫,纵然天隔一方,纵然我手中的刀刃已然破碎,也无法阻挡我寻找你的道路****</string>**
**</array>**
**</plist>**
*/

3.NSKeyedArchiver采用归档的形式来保存数据
NSKeyedArchiver保存数据对象需要遵守NSCoding协议,并且该对象对应的类必须提供encodeWithCoder:和initWithCoder:方法,简单的说就是告诉系统怎么对对象进行编码,怎么对对象进行解码. 下面就对Person这个对象进行归档保存:
Person.m文件:

class Person: NSObject {

    var name:String?
    var phone:String?

    // 构造方法
    init(name:String!,phone:String!) {
        self.name = name
        self.phone = phone

        super.init()
    }

    // 从NSObject解析回来

    init(coder aDecoder:NSCoder!){
        self.name=aDecoder.decodeObjectForKey("name") as? String
        self.phone=aDecoder.decodeObjectForKey("phone") as? String
    }

    //编码成object,哪些属性需要归档,怎么归档
    func encodeWithCoder(aCoder:NSCoder!){
        aCoder.encodeObject(name,forKey:"name")
        aCoder.encodeObject(phone,forKey:"phone")
    }

}

实现部分代码如下:

 private func  archiveSaveDataInfo(){
    // 储存自定义对象
    let userDefault = NSUserDefaults.standardUserDefaults()
    let mo = Person(name: "RookieYX", phone: "123456")
    // 实例对象转化成NSData
    let moData:NSData = NSKeyedArchiver.archivedDataWithRootObject(mo)
    // 储存NSData对象
    userDefault.setObject(moData, forKey: "myMo")
    // 自定义对象读取
    let myMoData = userDefault.objectForKey("myMo") as! NSData
    // 解档
    let myM= NSKeyedUnarchiver.unarchiveObjectWithData(myMoData) as! Person
    print(myM)

    }

/*
打印结果:
**<SwiftUserDefault.Person: 0x7fd958518450>**
**person ****名字****: Optional("Rookie")**
**person ****电话****: Optional("123456")**
*/

看了以上写的东西,我相信你已经对这三种简单的存储有了初步理解,那么我们就来检查一下自己的学习的知识吧,我们现在做一个简单的网络图片的本地缓存处理. 你可以先想一下,在继续看下去吧(⊙o⊙)…!(具体我直接贴代码)
函数实现部分:

    /**
     传递一个uiimageView,和图片路径,设置图片,异步操作

     - parameter newsImageView: UIImageView
     - parameter imageString:   网络图片地址
     */
   class func setImagesViewData(newsImageView:UIImageView,imageString:String){
        // 获取文件路径
        var catePath = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.CachesDirectory,NSSearchPathDomainMask.AllDomainsMask, true)
        print(catePath)
        let cateImagesUrl:NSURL = NSURL(fileURLWithPath: "\\(catePath.first)/\\(imageString.Rookie_MD5())")//获取缓存加密后的路径

        //缓存存在直接加载
        if let cateReadData:NSData  = NSData(contentsOfURL: cateImagesUrl){
            newsImageView.image = UIImage(data: cateReadData);
        }
        else{
            newsImageView.image = UIImage(named: "load.jpg");//默认图片
            //这里我们做个异步处理,用来加载图片
            let session = NSURLSession.sharedSession();
            let task = session.dataTaskWithURL(NSURL(string: imageString)!, completionHandler: { (imageData:NSData?, resp:NSURLResponse?, error:NSError?) in
                if let error = error {
                    print("连接网络失败1:\\(error)");
                }else{
                    // 当我们加载完数据了回主线程修改图片
                    if let endImageData = imageData{
                        dispatch_sync(dispatch_get_main_queue(), {
                            newsImageView.image = UIImage(data: endImageData)
                        })
                        // 写入本地
                        endImageData.writeToURL(cateImagesUrl, atomically: true)
                    }
                }
            })

            // 启动任务
            task.resume()
        }
    }

实现部分代码:

 private func cacheIntenetImage(){
        Tool.setImagesViewData(ImgView, imageString: URL)
    }

希望通过这篇文章可以对你有所帮助,因为我们在Swift学习之路上,如有错误之处,还请各位大 指出! ! 之后将会学习其他的数据存储方式,总结好之后也会更新在博客上, 有要学习的同学,可以关注一下me,可以通过这里互相学习一下,共同进步 ..



作者:叫我干苦力的小码农
链接:http://www.jianshu.com/p/efd358d53ffd
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
iOS 开发中,使用 Swift 实现本地存储和数据持久化有多种方法。根据数据的复杂性、持久化需求以及性能要求,可以选择合适的方式来实现。以下是几种常见的本地数据持久化方法及其使用场景。 ### 1. 使用 `UserDefaults` 存储轻量级数据 `UserDefaults` 是用于存储少量简单数据(如用户偏好、设置等)的轻量级方式。它适合存储字符串、整数、布尔值、数组、字典等基本类型。 ```swift let defaults = UserDefaults.standard defaults.set("John Doe", forKey: "username") let username = defaults.string(forKey: "username") ``` 这种方法适用于不需要频繁读写或结构化存储的场景[^3]。 ### 2. 使用 `FileManager` 进行文件读写 对于较大的数据或需要持久化存储的文件(如图片、日志文件等),可以使用 `FileManager` 将数据写入沙盒目录。Swift 提供了访问沙盒目录的方式,例如 `Documents`、`Caches` 和 `tmp`。 ```swift let fileManager = FileManager.default let urls = fileManager.urls(for: .documentDirectory, in: .userDomainMask) let documentDirectory = urls[0] let fileURL = documentDirectory.appendingPathComponent("data.txt") do { try "Hello, World!".write(to: fileURL, atomically: true, encoding: .utf8) let content = try String(contentsOf: fileURL, encoding: .utf8) } catch { print("Error writing to file: $error)") } ``` 该方法适用于需要将数据以文件形式保存的场景,例如缓存文件、用户文档等[^5]。 ### 3. 使用 `NSKeyedArchiver` 实现归档与解档(对象序列化) 当需要存储自定义对象时,可以采用归档(`NSKeyedArchiver`)和解档(`NSKeyedUnarchiver`)的方式。对象需要实现 `NSCoding` 协议。 ```swift class Person: NSObject, NSCoding { var name: String var age: Int init(name: String, age: Int) { self.name = name self.age = age } required init?(coder: NSCoder) { name = coder.decodeObject(forKey: "name") as? String ?? "" age = coder.decodeInteger(forKey: "age") } func encode(with coder: NSCoder) { coder.encode(name, forKey: "name") coder.encode(age, forKey: "age") } } let person = Person(name: "Alice", age: 30) let data = NSKeyedArchiver.archivedData(withRootObject: person) UserDefaults.standard.set(data, forKey: "personData") if let savedData = UserDefaults.standard.data(forKey: "personData"), let loadedPerson = NSKeyedUnarchiver.unarchiveObject(with: data) as? Person { print(loadedPerson.name) } ``` 该方法适合存储少量自定义对象,且不需要频繁读写的情况[^4]。 ### 4. 使用 `Core Data` 实现复杂数据持久化 `Core Data` 是苹果官方提供的数据持久化框架,适合处理结构化数据,支持关系建模、查询、版本迁移等功能。它适用于中大型应用中需要复杂数据管理的场景。 在使用 Core Data 时,开发者需要定义数据模型(`.xcdatamodeld`),并通过 `NSManagedObjectContext` 操作数据。 ```swift // 假设定义了一个名为 Person 的实体,包含 name 和 age 属性 let context = persistentContainer.viewContext let newPerson = Person(context: context) newPerson.name = "Bob" newPerson.age = 25 do { try context.save() } catch { print("Failed saving: $error)") } ``` Core Data 提供了强大的数据管理能力,适合构建具有复杂数据模型的应用[^2]。 ### 5. 使用第三方数据库框架 除了 Core Data,还可以使用第三方数据库框架来提升性能和开发效率,例如: - **Realm**:一个跨平台、高性能的移动端数据库,语法简洁,支持 Swift 和 Objective-C。 - **FMDB**:基于 SQLite 的封装,提供更易用的接口。 - **WCDB**:微信开源的数据库框架,支持多种查询方式,性能优异。 这些框架适合需要高性能、复杂查询和跨平台支持的应用场景[^5]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值