iOS - Swift 数据持久化

1、Sandbox 沙箱

  • iOS 为每个应用提供了独立的文件空间,一个应用只能直接访问为本应用分配的文件目录,不可以访问其他目录,每个应用自己独立的访问空间被称为该应用的沙盒。也就是说,一个应用与文件系统的交互绝大部分都被限制在它自己的应用沙盒内。
  • 1)在新 App 被安装时,安装器会为应用创建一系列角色不同的容器(container)。

    • iOS 8.0 之后,bundle 目录和沙盒目录 (Data) 是分开的。iOS 7.0 及以前版本 bundle 目录和沙盒目录 (Data) 是在一起的。
    • 1> Bundle Container:
      • MyApp.app :这就是应用的运行包(bundle),这个目录包含应用的可执行文件和所有资源文件。用户从 App Store 购买应用后,iTunes 安装到手机上的就是这个目录文件。这个目录是只读的,而且该目录在安装时进行了签名,安装后对该目录进行的任何写操作都会改变目录的签名内容,从而使的该应用无法启动,该应用本身能获得 bundle 中的任何文件的读权限。

            // 获取包路径
        
                let bundlePath:String = NSBundle.mainBundle().bundlePath
        
                let bundleUrl:NSURL = NSBundle.mainBundle().bundleURL
        
            // 获取应用程序程序包中资源文件路径
        
                let bundleFilePath:String? = NSBundle.mainBundle().pathForResource("testFile", ofType: "txt")
        
                let bundleFileUrl:NSURL? = NSBundle.mainBundle().URLForResource("testFile", withExtension: "txt")
    • 2> Data Container:
      • iTunes 在与 iPhone 同步时,备份所有的 Documents 和 Library 文件。iPhone 在重启时,会丢弃所有的 tmp 文件。
      • (1) Documents:
        • 保存由用户产生的文件或者数据,例如一个日记应用中用户写的日记文件,或者音乐播放器中用户下载的歌曲,涂鸦程序生成的图片,游戏关卡记录等。建议将用户可操作的文件数据都放到该目录。该文件夹下的内容不会被系统自动删除,但是严格规定必须是用户自己想要保存的。
        • 该目录下的所有文件都可以通过 iTunes 进行备份和恢复。存储在这里的所有文件会自动备份到 iCloud。该目录下如果保存了从网络下载的文件,在上架审批的时候,会被拒。
        • Documents/Inbox :该目录用来访问被外部应用所请求当前应用打开的文件。例如,我们的应用 MyApp 向系统注册了可以打开 doc 类型的文件,另一个应用 A 中有一个文件 read.doc ,并申请 MyApp 打开此文件,这时候系统会先将 read.doc 文件拷贝到 MyApp 应用中的 Documents/Inbox 目录下,MyApp 可以在 Inbox 目录下进行文件读取和删除,但是不能新建文件或者对已有文件进行写入。如果用户要对文件进行编辑,需要先将文件移动到其他目录。
            // 获取 Documents 路径
        
                let documentPath:String? = NSSearchPathForDirectoriesInDomains(.DocumentDirectory,
                                                                               .UserDomainMask,
                                                                               true)
                                                                               .last
        
                let documentUrl:NSURL? = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory,
                                                                               inDomains: .UserDomainMask)
                                                                               .last
      • (2) Library:
        • 该目录用来存储非用户数据,它下面包括几个标准的子目录,你可以将文件放到其中之一,也可以自己创建子目录。iOS 应用通常用到的子目录有 Preferences 和 Caches 。Library 目录下的文件通常是不应该暴露给用户的,该目录下除了 Caches 子目录外,其它目录及其文件都可以通过 iTunes 进行备份。
        • Library/Preferences :常用来放置配置文件、数据文件、模板等应用在运行中与用户相关,而又希望对用户不可见的文件,如系统偏好设置,用户偏好设置等文件。使用 NSUserDefaults 类进行偏好设置文件的创建、读取和修改。
        • Library/Caches :用来存放缓存文件,保存从网络下载的请求数据,后续仍然需要继续使用的文件,例如网络下载的离线数据,图片,视频文件等。该目录中的文件系统不会自动删除,可以做离线访问。它的存放时间比 tmp 下的长,但是不如 Library 下的其它目录。总的来说 Caches 目录下存放的数据不能是应用程序运行所必需的,但是能提高应用访问性能的。可写入应用支持文件,保存应用程序再次启动需要的信息。
        • iTunes 不会对这个目录的内容进行备份。要求程序员必需提供一个完善的清除缓存目录的 "解决方案"。
            // 获取 Library 路径
        
                let libraryPath:String? = NSSearchPathForDirectoriesInDomains(.LibraryDirectory,
                                                                              .UserDomainMask,
                                                                              true)
                                                                              .last
        
                let libraryUrl:NSURL? = NSFileManager.defaultManager().URLsForDirectory(.LibraryDirectory,
                                                                              inDomains: .UserDomainMask)
                                                                              .last
        
            // 获取 Caches 路径
        
                let cachesPath:String? = NSSearchPathForDirectoriesInDomains(.CachesDirectory,
                                                                             .UserDomainMask,
                                                                             true)
                                                                             .last
        
                let cachesUrl:NSURL? = NSFileManager.defaultManager().URLsForDirectory(.CachesDirectory,
                                                                             inDomains: .UserDomainMask)
                                                                             .last
      • (3) tmp:
        • 该目录用来存储临时文件,那些在下次重启中不需要再次载入的临时信息可以存放到该目录下。在应用不运行时,系统可能会对该目录下的内容进行清理。
        • 这个目录的内容不会通过 iTunes 备份。程序员不需要管 tmp 文件夹中的释放。
            // 获取临时文件路径
        
                let tmpPath:String = NSTemporaryDirectory()
  • 2)iOS 中同一个应用在不同的手机中分配的路径可能是不同的,所以我们无法通过硬编码指定完整路径名来找到对应文件。Foundation 框架提供了一组专门的接口来获取应用沙箱不同位置的目录路径。
        // 获取用户主路径
        public func NSHomeDirectory() -> String
    
        // 获取临时文件路径
        public func NSTemporaryDirectory() -> String
    
        // 获取满足条件的路径列表
        public func NSSearchPathForDirectoriesInDomains(directory: NSSearchPathDirectory,
                                                     _ domainMask: NSSearchPathDomainMask,
                                                    _ expandTilde: Bool) -> [String]
    • 该函数返回一组路径的数组,如果仅是查找用户的目录,这个数组只包含一个元素,如果第二个参数包含多个值,该数组会包含多个元素。当为 iOS 编写程序时,第二个参数应是 NSUserDomainMask,并且得到一个包含单个路径的数组作为返回。在 iOS 中后两个参数是不变的。
    • directory :指定查找的目录范围。
      NSSearchPathDirectory 说明
      ApplicationDirectory /Applications
      LibraryDirectory /Library
      DocumentDirectory /Documents
      ApplicationSupportDirectory /Library/Application Support
      UserDirectory /Users
      CachesDirectory /Library/Caches
    • domainMask :指定查找的文件系统域,可以是多值。
      NSSearchPathDomainMask 说明
      UserDomainMask 用户域,指向当前用户的 home 目录(~)
      LocalDomainMask 本地域,指向对所有用户可用的当前机器范围
      NetworkDomainMask 网络域,指向 /Network
      SystemDomainMask 系统域,指向 /System
    • expandTilde :指定是否展开路径中的代字符(~)。

2、NSBundle 路径

    public class NSBundle : NSObject
  • 在 iOS 中提到的 NSBundle 是文件系统中的一个特殊位置,它存放的是应用可执行文件及相关资源文件。这个位置的所有文件在系统运行时只具有可读或者可执行的权限,不能进行修改。
  • 应用程序 bundle 中主要有以下几种类型的文件:
    • Info.plist:用来配置应用的基本参数信息。包括版本号,指向的可执行文件名、包名等。
    • 可执行文件:每个应用程序必须要有一个可执行文件。
    • 资源文件:是可执行文件以外的数据文件,常用的如图像、图标、音频文件、视图文件、配置文件等。
  • 应用程序 bundle 的配置信息都存在 Info.plist 文件中。它里面各项都以 key-value 的形式进行描述,包括了应用程序唯一标识名、版本号、可执行文件名等信息。
  • bundle 配置信息主要参数:
    key 友好显示名 value
    CFBundleDisplayName Bundle display name 程序的应用名,安装后显示在桌面上的那个名称,可以进行本地化设置
    CFBundleExecutable Executable file 应用可执行程序的名称
    CFBundleIdentifier Bundle identifier 应用程序的唯一标识
    CFBundleVersion Bundle version 应用编译版本号
    CFBundleShortVersionString Bundle version string, short 应用 release 发布版版本号
  • 当创建一个应用时,系统存储了应用相关联的所有数据(其中包括图片、本地化字符串、图标等),将这些内容放入一个称为应用包(application bundle)的包中。在应用中添加一个资源时很方便的:仅需将文件拖到 Xcode 的左边窗格中。当出现对话框时,通常选择复制资源文件到你的项目目录中,这样你的项目都是自包含的。
  • command-line tool 是没有 bundle 的,所以用 NSBundle 的时候一直是 null,如果要使用 bundle 获取项目中的资源,必须要使用 application。
  • Bundle 常见问题
    • 项目里面的某个 .swift 文件无法使用

      • 检查 TARGETS => Build Phases => Compile Sources 里是否包含此 .swift 文件。
    • 项目里面的某个资源文件(比如 plist、音频等)无法使用
      • 检查 TARGETS => Build Phases => Copy Bundle Resources 里是否包含此资源文件。
  • 获取 NSBundle 资源
        // 获得 Bundle 信息
        /*
            通常指向 xxx.app/ 这个根目录
        */
        let mainBundle = NSBundle.mainBundle()
    
        // 获取 Bundle 文件路径
        let bundlePath:String = NSBundle.mainBundle().bundlePath
        let resourcePath:String? = NSBundle.mainBundle().resourcePath
    
        // 获取 Bundle URL 路径
        let bundleUrl:NSURL = NSBundle.mainBundle().bundleURL
        let resourceURL:NSURL? = NSBundle.mainBundle().resourceURL
    
        // 获得 Bundle 目录下的文件路径
    
            let filePath1:String = NSBundle.mainBundle().pathForResource("test", ofType: "txt")!
    
            // bundle 下子目录 inDirectory 下的文件路径
            let filePath2:String = NSBundle.mainBundle().pathForResource("test", ofType: "txt", inDirectory: "testFolder")!
    
        // 获得 Bundle 目录下的 URL 路径
    
            let fileUrl1:NSURL = NSBundle.mainBundle().URLForResource("test", withExtension: "txt")!
    
            // bundle 下子目录 subdirectory 下的 URL 路径
            let fileUrl2:NSURL = NSBundle.mainBundle().URLForResource("test", withExtension: "txt", subdirectory: "testFolder")!
    
        // 获取应用程序唯一标识包名
        let indentifier:String? = NSBundle.mainBundle().bundleIdentifier
    
        // 获取应用程序 Info.plist 配置项词典对象实例
        let info = NSBundle.mainBundle().infoDictionary
    
        // 获取某一特定字段的内容
        let bundleID:AnyObject? = NSBundle.mainBundle().objectForInfoDictionaryKey("CFBundleName")

3、NSURL 路径

    public class NSURL : NSObject, NSSecureCoding, NSCopying, NSURLHandleClient
    public class NSURLComponents : NSObject, NSCopying
  • 在文件系统中,文件和目录都是使用完整文件路径来唯一标识的。我们可以使用 NSString 和 NSURL 两种对象来描述文件路径。官方建议使用 NSURL 。
  • NSURL 是用来表示 URL 地址的类,通过 URL 我们可以定位一个远程 web 服务器上的资源位置,也可以定位硬盘上的一个本地文件的路径。对于 web 资源,往往结合 NSURLSession、NSURLConnection、NSURLDownload 等使用,对于本地资源,一般结合 NSFileManager、NSFileHandle、NSBundle 使用。
  • NSURLComponents 只支持 iOS7.0 及以上的 API 类,它可以实现对 URL 各个部分的读写。NSURLComponents 对 URL 各个部分的内容都有两种格式的属性来表示:
    原生格式 URL-Encoded
    scheme
    host percentEncodedHost
    port
    path percentEncodedPath
    query percentEncodedQuery
    fragment percentEncodedFragment
    user percentEncodedUser
    password percentEncodedPassword
  • 1)NSURL 结构:
        protocol://hostname[:port]/path/[;parameters][?query]#fragment        // 带方括号[]的为可选项
    
            protocol    :协议
            hostname    :主机名
            port        :端口
            path        :路径
            parameters  :参数
            query       :查询
            fragment    :信息片段
    
        如:https://swiftinaction.com/example?section=5
            这个 URL 包含 scheme(https)、host(swiftinaction.com)、path(/example)、query(section=5)等若干部分。
    
            其中 URL 的 scheme 字段标识了一个 URL 所遵循的协议:
    
                http://     超文本传输协议
                https://    超文本传输安全协议
                ftp://      文件传输协议
                file://     本地文件 URL
                data://     数据 URL
  • 2)URL 的创建
        // 由字符串创建
    
            // 简单字符串直接创建
            let url1:NSURL = NSURL(string: "https://swiftinaction.com/example")!
    
            let complexString:String = "https://swiftinaction.com/中文字符串/example"
            let convertString:String? = complexString.stringByAddingPercentEncodingWithAllowedCharacters(
                                                       NSCharacterSet(charactersInString: "`#%^{}\"[]|\\<> "))
    
            // 由复杂字符串/中文创建时,需要对字符串进行编码转换
            let url2:NSURL = NSURL(string: convertString!)!
    
            // 由基础 URL 和基于基础 URL 的一个相对路径字符串创建
            let baseUrl:NSURL = NSURL(string: "https://swiftinaction.com")!
            let fullUrl:NSURL = NSURL(string: "/example", relativeToURL: baseUrl)!
    
            // 生成绝对路径
            let url3:NSURL = fullUrl.absoluteURL
    
        // 由文件路径创建
    
            // 自动判断 URL 路径为文件,还是目录,为目录时自动在路径末尾加 “/”
            let url4:NSURL = NSURL.fileURLWithPath("/Users/JHQ0228/Desktop/test")
    
            // 指定 URL 路径为一个目录,自动在路径末尾加 “/”
            let url5:NSURL = NSURL.fileURLWithPath("/Users/JHQ0228/Desktop/test", isDirectory: true)
  • 3)URL 的获取
        let url1:NSURL = NSURL(string: "http://JHQ:password@swiftinaction.com:8080/sayHello/toChinese.png;
                                                                         date=20160223?name=JHQ#atMorning")!
    
        // 获取 URL 的 绝对路径字符串
        let absoluteString:String?    = url1.absoluteString
    
        // 获取 URL 的 协议类型
        let scheneString:String?      = url1.scheme
    
        // 获取 URL 的 主机名
        let hostString:String?        = url1.host
    
        // 获取 URL 的 端口
        let portString:NSNumber?      = url1.port
    
        // 获取 URL 的 路径名
        let pathString:String?        = url1.path
    
        // 获取 URL 的 参数
        let parametersString:String?  = url1.parameterString
    
        // 获取 URL 的 查询语句
        let queryString:String?       = url1.query
    
        // 获取 URL 的 信息片段语句
        let fragmentString:String?    = url1.fragment
    
        // 获取 URL 的 路径组成部分
        let pathComponents:AnyObject? = url1.pathComponents
    
        // 获取 URL 的 相对路径
        let relativePath:String?      = url1.relativePath
    
        // 获取 URL 的 路径最后一个组成部分
        let lastPathComponent:String? = url1.lastPathComponent
    
        // 获取 URL 的 路径扩展名
        let pathExtension:String?     = url1.pathExtension
    
        // 获取 URL 的 用户名
        let user:String?              = url1.user
    
        // 获取 URL 的 密码
        let password:String?          = url1.password
  • 4)URL 的判断
        let fileUrl:NSURL = NSBundle.mainBundle().URLForResource("testFile", withExtension: "txt")!
    
        // 检查文件的可达性
        /*
            只能用来判断文件系统内部资源的可达性,对于 web URl 等其他类型全返回 false
        */
        let bl1:Bool = fileUrl.checkResourceIsReachableAndReturnError(nil)
    
        // 判断是否为文件 URl
        let bl2:Bool = fileUrl.fileURL
  • 5)URL 的路径拼接
        let url:NSURL = NSURL(string: "http://swiftinaction.com/sayHello")!
    
        // 追加路径到当前路径末尾
    
            // 只追加路径,不在路径末尾添加 “/”
            let appendUrl1:NSURL = url.URLByAppendingPathComponent("toJhq")
    
            // isDirectory 为 true 时在路径末尾添加 “/”
            let appendUrl2:NSURL = url.URLByAppendingPathComponent("toJhq", isDirectory: true)
    
        // 追加路径后缀到当前路径末尾
        /*
            当路径以 “/” 结尾时,后缀会添加到末尾的 “/” 之前
        */
        let appendUrl3:NSURL = url.URLByAppendingPathExtension("png")
    
        // 删除路径末尾的最后一个路径
        let deleteUrl1:NSURL = appendUrl1.URLByDeletingLastPathComponent!
    
        // 删除路径末尾的后缀
        let deleteUrl2:NSURL = appendUrl3.URLByDeletingPathExtension!
  • 6)NSURLComponents
        let componentsUrl:NSURLComponents = NSURLComponents(string: "http://swiftinaction.com/sayHello")!
    
        componentsUrl.scheme = "https"
        componentsUrl.host = "swiftinaction.com.cn"
        componentsUrl.port = 8080
        componentsUrl.path = "/sayHello/toChinese/你好"
        componentsUrl.query = "name=JHQ"
        componentsUrl.fragment = "atMorning"
    
        componentsUrl.user = "JHQ"
        componentsUrl.password = "123456789"
    
        // 将 NSURLComponents 转为 NSURL
        let nsUrl:NSURL = componentsUrl.URL!
    
        let componentsUrlString1:String = componentsUrl.path!
    
        // 为内容数据的十六进制编码字符串
        let componentsUrlString2:String = componentsUrl.percentEncodedPath!

4、数据持久化

  • 在 iOS 开发过程中,不管是做什么应用,都会碰到数据保存的问题。将数据保存到本地,能够让程序的运行更加流畅,不会出现让人厌恶的菊花形状,使得用户体验更好。下面介绍一下数据保存的方式:

    • 1、NSKeyedArchiver
    • 2、NSUserDefaults
    • 3、Write to file
    • 4、SQLite
时间: 2024-10-23 19:08:32

iOS - Swift 数据持久化的相关文章

iOS中 数据持久化 UI高级_17

数据持久化的本质就是把数据由内写到本地(硬盘中),在iOS指将数据写到沙盒文件夹下: 沙盒机制:指的就是采用沙盒文件夹的形式管理应用程序的本地文件,而且沙盒文件夹的名字是随机分配的,采用十六进制方法命名: =======================关于沙盒目录========================== 沙盒内部构造: 测试沙盒: 属性: @interface ViewController () @property (retain, nonatomic) IBOutlet UITex

iOS学习之数据持久化详解

前言 持久存储是一种非易失性存储,在重启设备时也不会丢失数据.Cocoa框架提供了几种数据持久化机制: 1)属性列表: 2)对象归档: 3)iOS的嵌入式关系数据库SQLite3: 4)Core Data. 在iOS开发中,持久化数据的方法也并不限于属性列表.对象归档.SQLite3和Core Data.它们只是四种最常用且简单的方法.其实也可以使用传统C语言I/O调用(比如,fopen())读写数据,也可以使用Cocoa的底层文件管理工具.只不过这两种方法都需要写很多代码,并且没有必要这么做.

IOS swift 异步加载数据,并显示一个进度条

问题描述 IOS swift 异步加载数据,并显示一个进度条 网络获取数据使用的是NSURLConnection,异步请求.这个数据已经能够获得了.现在想要实现的是,通过登录界面输入账号什么的,点击提交按钮可以在显示进度条的同时执行post请求得到数据,如果这个数据不为空进度条消失并登录成功回到主界面,否者就提示有错. 希望小伙伴给个简单的例子,这样会更好理解 这个在安卓中是用AsyncTask实现的..线程一直都理不清,还请小伙伴们多多指导.谢谢!!!!! 解决方案 http://www.it

iOS数据持久化之一——plist文件

iOS数据持久化之一--plist文件         iOS开发中,我们时常会将一些简单的数据进行持久化的存储,方便我们保存程序的一些配置和用户的一些数据,plist文件就是我们保存这些数据的最佳选择. 一.何为plist         plist是一种文件格式,其内容规则是xml文件,后缀为.plist,因此,我们更习惯于成它问plist文件,在iOS开发中,这种文件常用来保存一些简单的配置数据,例如项目中的info.plist. 通过plist文件编辑器,我们可以很方便的查看和编辑层次清

iOS中几种数据持久化方案:我要永远地记住你!

概论 所谓的持久化,就是将数据保存到硬盘中,使得在应用程序或机器重启后可以继续访问之前保存的数据.在iOS开发中,有很多数据持久化的方案,接下来我将尝试着介绍一下5种方案: plist文件(属性列表) preference(偏好设置) NSKeyedArchiver(归档) SQLite 3 CoreData 沙盒 在介绍各种存储方法之前,有必要说明以下沙盒机制.iOS程序默认情况下只能访问程序自己的目录,这个目录被称为"沙盒". 1.结构 既然沙盒就是一个文件夹,那就看看里面有什么吧

iOS 通过CoreData实现数据持久化

引言: Core Data 是 iOS 3.0 以后引入的数据持久化解决方案,其原理是对SQLite的封装,是开发者不需要接触SQL语句,就可以对数据库进行的操作. 其编码方式和原理结构方面较为特殊,本博文主要介绍在使用Core Data时遇到的各种问题以及对其核心原理进行解释. 参考资料:  1: iOS教程:Core Data数据持久性存储基础教程 http://www.dasheyin.com/ios_jiao_cheng_core_data_shu_ju_chi_jiu_xing_cun

iOS数据持久化之二——归档与设计可存储化的数据模型基类

iOS数据持久化之二--归档与设计可存储化的数据模型基类 一.引言         在上一篇博客中,我们介绍了用plist文件进行数据持久化的方法.虽然简单易用,但随着开发的深入,你会发现,这种方式还是有很大的局限性.试想,如果我们可以将用户的登录返回信息模型,游戏中角色的属性信息模型进行直接的持久化存取,那是不是非常爽的事,幸运的是,我们可以通过归档,来设计一个这样的数据模型. 二.先来精通归档吧         归档也是iOS提供给开发者的一种数据存储的方式,事实上,几乎所有的数据类型都可以

iOS用两行代码完美解决数据持久化_IOS

前言 在实际的iOS开发中,有些时候涉及到将程序的状态保存下来,以便下一次恢复,或者是记录用户的一些喜好和用户的登录信息等等. 这就需要涉及到数据的持久化了,所谓数据持久化就是数据的本地保存,将数据从内存中迁入到存储器上.网上有很多种数据持久化的方法,如实现自己实现I/O.数据库.云或则走第三方接口等等.但是有时候可能只是进行一些简单的数据存储,如用户的偏好设置.用户的sessionID等等,这时候使用上述方法便显得有点兴师动众了,现在需要一种更加轻量化的操作方式. 一.认识 NSUserDef

iOS - Swift NSUserDefaults 数据存储

前言 public class NSUserDefaults : NSObject 用来保存应用程序设置和属性.用户保存的数据.用户再次打开程序或开机后这些数据仍然存在.如果往 userDefaults 里存了一个可变数组,取出来的时候这个数组对象就变成了不可变的. NSUserDefaults 可以存储的数据类型包括:NSData.NSString.NSNumber.NSDate.NSArray.NSDictionary.如果要存储其他类型,则需要转换为前面的类型,才能用 NSUserDefa