• 前言 之前在这篇文章里 我们定义了一个Parsable 用于...复制代码如果我们要给自定义的类型添加一个持久化的功能,同样也可以定义一个协议,使得遵守这个协议的类型都拥有持久化这个功能。 Cachable public protocol...

    前言

    之前在这篇文章里 我们定义了一个Parsable 用于反序列化

    protocol Parsable {
      static func parse(data: Data) -> Result<Self>
    }
    复制代码

    如果我们要给自定义的类型添加一个持久化的功能,同样也可以定义一个协议,使得遵守这个协议的类型都拥有持久化这个功能。

    Cachable

    public protocol Cachable {
      /// 存入沙盒
      ///
      /// - Parameter path: 路径
      /// - Returns: 结果
      @discardableResult
      func save(at path: String) -> Result<Void, Error>
    
      /// 从沙盒中取
      ///
      /// - Parameter path: 路径
      /// - Returns: 结果
      static func get(fromCache path: String) -> Self?
    }
    复制代码

    Cachable定义了两个方法 存和取,接下来我们给Cachable添加默认实现。

    Codable

    大部分的反序列化与序列化都会使用非常方便Codable

    extension Cachable where Self: Codable {
      @discardableResult
      public func save(at path: String) -> Result<Void, Error> {
        let url = URL(fileURLWithPath: path)
        do {
          let data = try JSONEncoder().encode(self)
          try data.write(to: url)
          return .success(())
        } catch {
          print("Cachable: 存储沙盒失败 - \(error.localizedDescription)")
          return .failure(error)
        }
      }
    
      public static func get(fromCache path: String) -> Self? {
        let url = URL(fileURLWithPath: path)
        do {
          let data = try Data(contentsOf: url)
          return try JSONDecoder().decode(self, from: data)
        } catch {
          print("Cachable: 从沙盒中获取失败 - \(error.localizedDescription)")
          return nil
        }
      }
    }
    复制代码

    如此一来当一个类型遵循了Codable且也想遵循Cachable就可以免费使用上面的两个方法。

    struct Car: Codable {
      var engine: String
      var name: String
      var type: String
    }
    
    extenstion Car: Cachale {}
    
    // 获取沙盒中缓存的car
    let carCachePath = getMyCarCachePath()
    let myCacheCar = Car.get(fromCache: carCachePath)
    
    // 缓存bmw
    let bmw = Car(engine: "V8", name: "X7", type: "xDrive50i")
    bmw.save(at: carCachePath)
    复制代码

    注:我们使用@discardableResult标记了save(at:)方法,目的是让编译器不警告我们没有使用save(at:)方法的返回值。很多链式调用的方法都有这个标记,例如Alamofire就使用了这个标记。

    String、Data

    我们也可以给StringData也添加这个功能。

    extension Cachable where Self == String {
      @discardableResult
      public func save(at path: String) -> Result<Void, Error> {
        let url = URL(fileURLWithPath: path)
        do {
          if let data = self.data(using: .utf8) {
            try data.write(to: url)
            return .success(())
          } else {
            return .failure(WWError.stringToDataError)
          }
        } catch {
          print("Cachable: 存储沙盒失败 - \(error.localizedDescription)")
          return .failure(error)
        }
      }
    
      public static func get(fromCache path: String) -> Self? {
        let url = URL(fileURLWithPath: path)
        do {
          let data = try Data(contentsOf: url)
          return self.init(data: data, encoding: .utf8)
        } catch {
          print("Cachable: 从沙盒中获取失败 - \(error.localizedDescription)")
          return nil
        }
      }
    }
    复制代码

    Data也是一样的,大家可以自行去实现。

    SwiftProtobuf

    如果有使用SwiftProtobuf也可以给SwiftProtobufMessage添加这个功能。

    extension Cachable where Self: SwiftProtobuf.Message {
      @discardableResult
      func save(at path: String) -> Result<Void, Error> {
        let url = URL(fileURLWithPath: path)
        do {
          let data = try serializedData()
          try data.write(to: url)
          return .success(())
        } catch {
          print("Cachable: 存储沙盒失败 - \(error.localizedDescription)")
          return .failure(error)
        }
      }
    
      static func get(fromCache path: String) -> Self? {
        let url = URL(fileURLWithPath: path)
        do {
          let data = try Data(contentsOf: url)
          return try self.init(serializedData: data)
        } catch {
          print("Cachable: 从沙盒中获取失败 - \(error.localizedDescription)")
          return nil
        }
      }
    }
    复制代码

    添加了默认实现后,我们的Cachable已经可以大展身手了,只要是满足Codable或是SwiftProtobuf里的Message并且遵循了Cachable就可以免费持久化了。

    总结

    protocol绝对是用来描述某种功能的利器,而且不受类型的限制,万物皆可遵循。想要JSON转model就遵循Decodable,想要持久化某个对象就遵循我们的Cachable...

    只要你想提供某种功能,使用protocol抽象,给它添加默认实现,谁想用这个功能就遵循它,不想用也不会多余。

    转载于:https://juejin.im/post/5cfb67cb6fb9a07ee958622b

    展开全文
  • 前言:数据持久化 存储:一个很常见的话题;在手机上不管是android、还是 iOS 系统上;都支持数据持久化保存;操作数据保存的方式有多种,但想要持久存储在磁盘上,最终都会以文件(xml、sqlite) 或者 二进制...
    前言:数据持久化 存储:一个很常见的话题;在手机上不管是android、还是 iOS 系统上;都支持数据持久化保存;操作数据保存的方式有多种,但想要持久存储在磁盘上,最终都会以文件(xml、sqlite) 或者 二进制(binary store) 的形式存储在磁盘上;其他方式 不考虑,今天主要来说说 sqlite
    

    百度百科中 SQLite的描述;

    SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。它是D.RichardHipp建立的公有领域项目。它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源的世界著名数据库管理系统来讲,它的处理速度比他们都快。SQLite第一个Alpha版本诞生于2000年5月。 至2015年已经有15个年头,SQLite也迎来了一个版本 SQLite 3已经发布。

    sqlite 关系型数据库;

    在android 、iOS系统中都支持的数据库,底层其实就是一个文件;如果有过 java 中连oracle ,c#中连 sqlserver ,android中 连sqlite 的经验的话,大家都知道 连接过程有个 连接池 这么一个 说法; 而coreData 他是一个框架,他又是 将 oc 或swift 与 sqlite 的语句 分开;直接存储对象;省去了sqlite 的一些操作,就能够实现 存储过程;
    这两天在用coredata 的过程中,我一直在参考别人的用法;今天我自己也总结一下;

    coreData 的使用

    建工程、创建.xcdatamodel 文件就不说了;在创建好.xcdatamodel 文件后,在之前 都是要去 editor ->create nsmangerobject subclass;在swift4 上,这个过程去掉了,你在.xcdatamodel文件里创建 entry 时,xcode 已经帮你对应的创建好了 entry 类;直接用就可以了;

    我们具体所关心的是 增删 改查,因为具体对应到我们的应用中;我们最关心的就是我们的业务;哪些需要保存,哪些需要删除;上面也说了;coredata 能够对 对象 进行 存储;要存储的对象都要继承 NSManagedObject;
    在进行操作前;我们首先要跟 数据库 ,打通连接;

    具体例子:

    1、生成当前上下文
       ///当前上下文
       public  lazy var mangerContext: NSManagedObjectContext = {
            let context = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
            ///需要设置一个调度器
            context.persistentStoreCoordinator = self.persistentStoreCoordinator
            return context
        }()
     2、调度器的创建
      ///调度器  设置保存的路径
       public lazy var   persistentStoreCoordinator:NSPersistentStoreCoordinator = {
          //需要保存的Datamodle
            let coordinator = NSPersistentStoreCoordinator(managedObjectModel:self.mangerModel)
            let dirURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last
            let fileURL = URL(string: "db.sqlite", relativeTo: dirURL)
    
            do {
                try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: fileURL, options: nil)
            } catch {
                fatalError("Error configuring persistent store: \(error)")
            }
            return coordinator
        }()
     3、  DataModel
      //调度器管理 model 也就是 创建的DataModel
        public   lazy var mangerModel:NSManagedObjectModel = {
            guard let url = Bundle.main.url(forResource: "CoreDataStudy", withExtension: "momd") else{
                fatalError("加载错误")
            }
            guard let model = NSManagedObjectModel(contentsOf: url) else{
                fatalError("加载错误")
            }
            return model
        }() 
    

    通过以上三步;就有了context

    数据的增删改查;
    我这里 写个 增与查的例子;

    添加:

        @IBAction func add(_ sender: Any) {
            //要保存的model
            let one:Student  = NSEntityDescription.insertNewObject(forEntityName: "Student", into: self.mangerContext) as! Student
            one.name = name.text
            do {
               try  self.mangerContext.save()
            }catch{
                fatalError("保存失败")
            }

    查询

     @IBAction func findnames(_ sender: Any) {
         //查询请求
             let request:NSFetchRequest = Student.fetchRequest()
             //这里可以加入查询的条件
             。。。
              //啥都不加 ,就是全部查询出来
            do{
               let result =  try mangerContext.fetch(request)
                self.studens = result
                namelist.reloadData()
            }catch{
                fatalError("查询失败")
            }
        }

    效果演示:这里写图片描述

    就到这里了;只是浅显的使用;具体详细的了解,还需要深入的学习;coredata 的使用,大家如果有sqlite 或者其他数据库使用的基础的话,这个用起来还是非常容易上手的;

    个人简历地址:18年想换个新工作,希望可以和志同道合的朋友一起工作;一起提升能力,18年 ,加油!
    http://bmob-cdn-6585.b0.upaiyun.com/2018/01/11/08ae8ec7402ce7d780aeb590b858a6dc.pdf

    展开全文
  • 数据持久化一直是 iOS 开发中必修之课。比较常见的数据持久化方式有以下5种: 1.plist文件(属性列表) 2.preference(偏好设置) 3.NSKeyedArchiver(归档) 4.SQLite 3 5.CoreData 今天主要研究的是...

    数据持久化一直是 iOS 开发中必修之课。比较常见的数据持久化方式有以下5种: 1.plist文件(属性列表) 2.preference(偏好设置) 3.NSKeyedArchiver(归档) 4.SQLite 3 5.CoreData

    今天主要研究的是NSKeyedArchiver的使用。

    NSKeyedArchiver在iOS中是序列化的一种形式,只要遵循了NSCoding协议的对象都可以通过它实现序列化。值得庆幸的是决大多数支持存储数据的Foundation和Cocoa Touch类都遵循了NSCoding协议,因此,对于大多数类来说,归档相对而言还是比较容易实现的。

    接下来的示例存储的都是 Data 类型的数据,Data 是遵循了 NSCoding 协议的。

    一、存储路径的设置,路径最好设置为全局变量

    var filePath : String {
    	let manager = FileManager.default
    	let url = manager.urls(for: .documentDirectory, in: .userDomainMask).first! as NSURL
    	return url.appendingPathComponent("objects")!.path
    }
    复制代码

    二、存储、归档

    // 存储到第一步设置的路径之下  value 就是你要存储的数据
    NSKeyedArchiver.archiveRootObject(value, toFile: filePath)
    复制代码

    三、从路径之下读取

    // 读取出来的数据格式就是你当时存储的格式,你存的 Data读取的就是 Data ,你存Model 读取的就是 Model。 注意读取出来的 value 是一个可选值 ,需要做处理之后使用
    let  value = NSKeyedUnarchiver.unarchiveObject(withFile: filePath)
    复制代码

    四、删除。当我们要销毁这个数据应该怎么做呢

    // 删除数据,运用的场景有退出登录等
    	let exists = FileManager.default.fileExists(atPath: filePath)
    		if exists {
    			do {
                 // 删除路径下存储的数据,做了错误处理,运用do-catch处理,不太理解do-catch的我的文章中有
    				try FileManager.default.removeItem(atPath: filePath)
                 // 下边两行代码是界面转换和一些数据的处理  可以根据自己的需求来做
    				self.dismiss(animated: true, completion: nil)
    				self.delegate?.reloadLastViews()
    			}catch let error as NSError {
    				
    				print("error: \(error.localizedDescription)")
    		
    			}
    		}
    复制代码

    但是对于本身不遵循 NSCoding 协议的数据类型,要遵循协议之后才能归档。例如我们的 Model 在 Swift 中实现两个方法:

    // 以下两个方法是 NSCoding 协议的两个方法  
    	/**
    	* NSCoding required initializer.
    	* Fills the data from the passed decoder
    	*/
    // 解档  根据 JSON数据中的字段,分解为我们需要的属性
    	@objc required init(coder aDecoder: NSCoder)
    	{
    		data = aDecoder.decodeObject(forKey: "data") as? CurrentUserData
    		isFail = aDecoder.decodeObject(forKey: "isFail") as? Bool
    		isOk = aDecoder.decodeObject(forKey: "isOk") as? Bool
    		
    	}
    	
    	/**
    	* NSCoding required method.
    	* Encodes mode properties into the decoder
    	*/
    // 归档  根据属性和对应的字段进行归档
    	func encode(with aCoder: NSCoder)
    	{
    		if data != nil{
    			aCoder.encode(data, forKey: "data")
    		}
    		if isFail != nil{
    			aCoder.encode(isFail, forKey: "isFail")
    		}
    		if isOk != nil{
    			aCoder.encode(isOk, forKey: "isOk")
    		}
    		
    	}
    复制代码

    然后再根据上边的四个步骤来做就可以了

    展开全文
  • 文/helloDolin(简书作者) ... 著作权归作者所有,转载请联系作者...iOS下数据持久化常用的几种方式: NSUserDefaultsplist(属性列表)NSKeyedArchiver(对象归档)iOS的嵌入式关系数据库SQLite3 苹果公司提供的持
    文/helloDolin(简书作者)
    原文链接:http://www.jianshu.com/p/934a14e6de49
    著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

    iOS下数据持久化常用的几种方式:

    • NSUserDefaults
    • plist(属性列表)
    • NSKeyedArchiver(对象归档)
    • iOS的嵌入式关系数据库SQLite3
    • 苹果公司提供的持久化工具 Core Data

    上面几种方式,有一个共同的要素,就是应用的/Documents文件夹。每个应用都有自己的/Documents文件夹,且仅能读写各自/Documents文件中的内容


    先让我们我们看看sandbox(沙盒)
    将手机与电脑连接好之后,按如下步骤进行操作


    步骤1

    步骤2

    步骤3

    另一种方式


    下载这个文件.png

    下载这个文件我们会得到一个.xcappdata的文件


    xcappdata.png

    右键显示包内容


    右键显示包内容

    逐一打开你要的文件吧



    沙盒目录结构清晰的展现在我们眼前

    • Documents:保存应用运行时生成的需要持久化的数据,iTunes同步设备时备份该目录。例如,游戏应用可将游戏存档保存在该目录
    • tmp:保存应用运行时所需的临时数据,使用完毕后再将相应的文件从该目录删除。应用没有运行时,系统也可能会清除该目录下的文件。iTunes同步设备时 不会 备份该目录
    • Library/Caches:保存应用运行时生成的需要持久化的数据,iTunes同步设备时 不会 备份该目录。一般存储体积大、不需要备份的非重要数据
    • Library/Preference:保存应用的所有偏好设置,iOS的Settings(设置)应用在该目录中查找应用的设置信息。iTunes同步设备时备份该目录

    NSUserDefaults:

    直接上代码:

    static NSString* const key = @"key";
    [[NSUserDefaults standardUserDefaults] setValue:@"YES" forKey:key];
    [NSUserDefaults standardUserDefaults] valueForKey:key]
    [userDefaults removeObjectForKey:key];
    [userDefaults synchronize];

    上面的示例代码基本就是NSUserDefaults所有用法了,虽然很简单,但还是有几点需要注意:

    1. 建议将所有的的key单独存放(好处自己领会)
    2. NSUserDefaults可以存储的数据类型包括:NSData、NSString、NSNumber、NSDate、NSArray、NSDictionary。如果要存储其他类型,则需要转换为前面的类型,才能用NSUserDefaults存储。之前碰到个坑就是从服务器拿到数据部分用这种方式存储,服务器返回NSNull,我们这边也没有model层转,就直接存储了,导致app卡掉但并没有闪退之类,就是线程卡死的情况
    3. 同步问题,在适当的时候同步。因为synchronize的开销可能会很大,因为要比较内存中和存储中的所有用户偏好默认值,如果有好几百个key value 同步是非常消耗性能的。
    4. 偏好设置是专门用来保存应用程序的配置信息的,( 用过Settings.bundle的应该都很熟悉),所以一般不要在偏好设置中保存其他数据。
    5. 偏好设置会将所有数据保存到同一个文件中。即preference目录下的一个以此应用包名来命名的plist文件。

    plist(属性列表):

    首先需要知道什么是序列化对象(serialized object):指可以被转换为字节流以便于存储到文件中或通过网络进行传输的对象

    可以被序列化的类型只有如下几种:
    NSArray
    NSMutableArray
    NSDictionary
    NSMutableDictionary
    NSData
    NSMutableData
    NSString
    NSMutableString
    NSNumber
    NSDate

    还是直接上代码示例

    /**
     *  获取存储路径
     */
    - (NSString*)dataFilePath {
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentDirectory = paths[0];
        return [documentDirectory stringByAppendingPathComponent:@"data.plist"];//nsstring真强大
    }

    我们在app处于非活跃状态时存储一些东东

    UIApplication* app = [UIApplication sharedApplication];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appWillResignActive:) name:UIApplicationWillResignActiveNotification object:app];
    
    - (void)appWillResignActive:(NSNotification*)notification {
        NSString* filePath = [self dataFilePath];
        NSArray* arr = @[@1,@2,@3,@4];
        [arr writeToFile:filePath atomically:YES];
    }

    在我们需要这些东东的时候从文件中读取

    NSString* filePath = [self dataFilePath];
    if ([[NSFileManager defaultManager]fileExistsAtPath:filePath]) {
        NSArray* arr = [[NSArray alloc]initWithContentsOfFile:filePath];
    }

    NSKeyedArchiver(对象归档):

    在Cocoa中,Archiver是另一种形式的序列化,是任何对象都可实现的更常规的类型

    说明:

    1. 只有遵守了NSCoding或 NSSecureCoding(更为安全的归档协议)协议,并且实现了协议里归档与解归档的方法的的类创建的对象才能够进行归档
    2. 最好也实现以下NSCopying,NSCopying与NSCoding一起实现好处在于允许复制对象,使用数据模型对象时有较大的灵活性

    还是直接上代码

    #import <Foundation/Foundation.h>
    @interface FourLines : NSObject<NSCoding,NSCopying>
    
    @property(copy,nonatomic)NSArray* lines;
    
    @end
    
    #import "FourLines.h"
    
    //编解码的key
    static NSString* const klinesKey = @"klinesKey";
    
    @implementation FourLines
    
    #pragma mark -  NSCoding
    
    - (void)encodeWithCoder:(NSCoder *)aCoder {
        [aCoder encodeObject:self.lines forKey:klinesKey];
    }
    
    - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder {
        self = [super init];
        if (self) {
            self.lines = [aDecoder decodeObjectForKey:klinesKey];
        }
        return self;
    }
    
    #pragma mark -  NSCopying 
    
    - (id)copyWithZone:(nullable NSZone *)zone {
        FourLines* copy = [[[self class]allocWithZone:zone]init];
        NSMutableArray* linesCopy = [NSMutableArray array];
        for (id line in self.lines) {
            [linesCopy addObject:[line copyWithZone:zone]];
        }
        copy.lines = linesCopy;
        return copy;
    }
    
    @end

    写入数据,编码:文件路径还是用上面代码中定义的文件路径

    - (void)appWillResignActive:(NSNotification*)notification {
        NSString* filePath = [self dataFilePath];
        FourLines* lines = [[FourLines alloc]init];
        lines.lines = @[@"a",@"b",@"c",@"d"];
        NSMutableData* data = [[NSMutableData alloc]init];
        NSKeyedArchiver* archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];
        [archiver encodeObject:lines forKey:kRootKey];
        [archiver finishEncoding];
        [data writeToFile:filePath atomically:YES];  
    }

    读取数据,解码:

    NSString* filePath = [self dataFilePath];
     if ([[NSFileManager defaultManager]fileExistsAtPath:filePath]) {
            NSData* data = [[NSMutableData alloc]initWithContentsOfFile:filePath];
            NSKeyedUnarchiver* unarchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:data];
            FourLines* four = [unarchiver decodeObjectForKey:kRootKey];
            [unarchiver finishDecoding];
            for (int i = 0; i < 4; i++) {
                //to do
            }
    }
    
    UIApplication* app = [UIApplication sharedApplication];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appWillResignActive:) name:UIApplicationWillResignActiveNotification object:app];

    iOS的嵌入式关系数据库SQLite3 :

    这里跳过SQLite3,直接上FMDB
    简介

    FMDB是iOS平台的SQLite数据库框架,它是以OC的方式封装了SQLite的C语言API,它相对于cocoa自带的C语言框架有如下的优点:
    使用起来更加面向对象,省去了很多麻烦、冗余的C语言代码
    对比苹果自带的Core Data框架,更加轻量级和灵活
    提供了多线程安全的数据库操作方法,有效地防止数据混乱
    注:FMDB的gitHub地址

    本文不进行详解


    苹果公司提供的持久化工具 Core Data:

    这里主要说明以下谓词的概念:类似SQL的where定义条件
    在创建项目的时候


    注意勾选此处


    具体使用不进行详解


    希望能给大家带来帮助O(∩_∩)O

    展开全文
  • 在处理Swift持久化内容的时候,使用到了NSUserDefaults来保存数据,但是在实现过程中发现正常的对象无法保存,会报很多错,对象如下(简单的Student对象) class Student { var name: String? var id: Int? }该...

    在处理Swift持久化内容的时候,使用到了NSUserDefaults来保存数据,但是在实现过程中发现正常的对象无法保存,会报很多错,对象如下(简单的Student对象)

    class Student {
      var name: String?
      var id: Int?
    }
    该对象在存储过程中,即如下方式存储时会报各种错误

    let student = Student()
    let defaults = NSUserDefaults.standardUserDefaults()
    defaults.setObject(strDict, forKey: "strDict")
    defaults.synchronize()

    其中需要继承NSObject类和NSCoding类,并且需要重写NSObject类中的description属性(如果需要的话)和无参构造,NSCoding类中的

    requiredinit?(coder aDecoder: NSCoder)构造和

    encodeWithCoder(aCoder:NSCoder)方法

    改造如下:

    class Student: NSObject, NSCoding{
        var name: String?
        var id: Int?
        override var description: String {
            get {
                return "name: " + name! + "  id: \(id)"
            }
        }
        
        override init() {
            
        }
        
        required init?(coder aDecoder: NSCoder) {
            self.id = aDecoder.decodeObjectForKey("id") as? Int
            self.name = aDecoder.decodeObjectForKey("name") as? String
        }
        
        func encodeWithCoder(aCoder: NSCoder) {
            aCoder.encodeObject(name, forKey: "name")
            aCoder.encodeObject(id, forKey: "id")
        }
    }
    
    无参构造不必实现什么或者赋值什么,如果你想在构造时就对对象属性赋值也可以重写有参构造

    改造完毕之后借助NSData来实现在NSUserDefaults中对象的保存,代码如下所示:这里仅以Array类型作为示例,当类继承了NSObject和NSCoding后,对象,Array,Dictionary均能正常的存储

    var students = [Student]()
    students.append(student1)
    students.append(student2)
    students.append(student3)
                
    let data: NSData = NSKeyedArchiver.archivedDataWithRootObject(students)
    defaults.setObject(data, forKey: "array")
    下面这句话我也在网上查了好多资料,其实是写不写都一样,只是用来保证在异常关闭前能存储正常
    defaults.synchronize()
    读取方式如下:

    let one = defaults.objectForKey("array") as? NSData
    if one != nil {
    <span style="white-space:pre">	</span>let student = NSKeyedUnarchiver.unarchiveObjectWithData(one!)
    <span style="white-space:pre">	</span>print((student as! [Student]).description)
    }

    以上,本人初学Swift,如有错误的地方,还请不吝指正,多谢


    展开全文
  • swift 工程中要保存类对象数组,经综合考虑选用UserDefaults 及 NSSecureCoding 保存类对象数组。首先定义类: class TimeData:NSObject, NSSecureCoding { static var supportsSecureCoding: Bool { return true...
  • 本篇主要整理了Swift中对于字符串、数组和 Model 的读写操作,其中还包括了序列反序列以及归档解档的知识。
  • iOS有一套完整的数据安全体系,iOS应用只能访问自己的目录,这个目录被称为沙箱目录,应用程序之间禁止数据的共享和访问。一些特定的应用,如联系人应用,必须通过特定的API来访问。 1、沙箱目录 ...
  • sqlite3数据持久化

    2019-06-13 01:10:32
    为什么80%的码农都做不了架构师?>>> ...
  • 前言 嗯,你们要的大招。跟着这篇文章一起也发布了CTPersistance和CTJSBridge这两个库,希望大家在实际使用的时候如果遇到...尤其是在服务端,持久化方案的优劣往往都会在一定程度上影响到产品的性能。然而
  • 前言 嗯,你们要的大招。跟着这篇文章一起也发布了CTPersistance和CTJSBridge这两个库,希望大家在实际使用的时候如果遇到...尤其是在服务端,持久化方案的优劣往往都会在一定程度上影响到产品的性能。然而
  • 基本使用方法: let defaults = UserDefaults.standard 添加 defaults.set(123, forKey: "defaultKey") 获取 defaults.integer(forKey: "defaultKey") ...对此方法进行封装 调用 ...
  • Core Data是有苹果官方提供的框架(#import ),实现数据持久化存储。Core Data实际上是将数据库的创建、表的创建、对象和表的转换等操作封装起来,极大的简化了操作。使用Core Data进⾏数据库存取不需要手动创建...
  • 前言 嗯,你们要的大招。跟着这篇文章一起也发布了CTPersistance和CTJSBridge这两个库,希望大家在实际使用的时候如果遇到...尤其是在服务端,持久化方案的优劣往往都会在一定程度上影响到产品的性能。然而
  • 本地存储NSUserdefault封装(可存储各种类型),简单易用。 调用方法: #import "ViewController.h" #import "StudentModel.h" #import "InfoModel.h" #import "NSObject+JKLocalStore.h" @interface ...
  • 众所周知,Core Data 是苹果内置关于用户数据持久化的解决方案,无论在 iOS 平台还是 OS X 平台,它都是通用的。尽管苹果一直秉持着最大化的使编程简单的宗旨,但是 Core Data 上手对于有经验的开发者也不是一件易事...
  • 持久化方式就是数据存储方式.iOS支持本地存储和云端存储,而本地存储主要涉及如下三种机制: 属性列表:集合对象可以读写到属性列表中; SQLite数据库:SQLite是一个开源嵌入式关系型数据库; CoreData:是一种对象关系映射...
1 2 3 4 5 ... 20
收藏数 1,317
精华内容 526