为啥这个 plist 读/写失败?

Posted

技术标签:

【中文标题】为啥这个 plist 读/写失败?【英文标题】:Why is this plist read/write failing?为什么这个 plist 读/写失败? 【发布时间】:2018-02-21 15:49:08 【问题描述】:

我正在学习 ios 教程,但遇到了 plist 问题。我有这个反射代码,我的应用程序中的模型对象:

struct Reflection 
let title: String
let body: String
let author: String
let favorite: Bool
let creationDate: Date
let id: UUID


extension Reflection 
var plistRepresentation: [String: AnyObject] 
    return [
        "title": title as AnyObject,
        "body": body as AnyObject,
        "author": author as AnyObject,
        "favorite": favorite as AnyObject,
        "creationDate": creationDate as AnyObject,
        "id": id as AnyObject
    ]


init(plist: [String: AnyObject]) 
    title = plist["title"] as! String
    body = plist["body"] as! String
    author = plist["author"] as! String
    favorite = plist["favorite"] as! Bool
    creationDate = plist["creationDate"] as! Date
    id = plist["id"] as! UUID


然后我有这个存储控制器:

class StorageController 
fileprivate let documentsDirectoryURL = FileManager.default
    .urls(for: .documentDirectory, in: .userDomainMask)
    .first!

fileprivate var notesFileURL: URL 
    return documentsDirectoryURL
        .appendingPathComponent("Notes")
        .appendingPathExtension("plist")


func save(_ notes: [Reflection]) 
    let notesPlist = notes.map  $0.plistRepresentation  as NSArray
    notesPlist.write(to: notesFileURL, atomically: true)


func fetchNotes() -> [Reflection] 

    guard let notePlists = NSArray(contentsOf: notesFileURL) as? [[String: AnyObject]] else 
        print("No notes")
        return []
    
    print("Notes found")
    return notePlists.map(Reflection.init(plist:))


当我调用 save() 并尝试写入 plist 时,我没有收到任何错误。但是,当我调用fetchNotes() 时,它会打印“No Notes”,这意味着使用这些内容的数组是 nil 或者它不能转换为字典。为什么会这样?

【问题讨论】:

使用init(contentsOf url: URL, error: ()) throws 会抛出error 和try/catch 怎么样?也许那里有一些信息。此外,强制转换(as ! [[String:AnyObject]] 可能会记录一些内容)。 这似乎是一个非常糟糕或过时的教程。读写属性列表的推荐方法是PropertyListSerialization——它提供了良好的错误处理——对象值是Any而不是AnyObject。在 Swift 4 中,您甚至可以使用Codable 协议和PropertyListEn-/Decoder,这会将结构中的代码减少到属性声明行。 @vadian 会调查的。遵循 Matteo Manferdini 制作专业 iOS 应用程序的终极课程。好像很更新了…… 属性列表字典的类型 [String:AnyObject] 在 Swift 3+ 中不合适。所有属性列表类型都是值类型 (Any)。这也避免了丑陋的桥梁投射到AnyObject 【参考方案1】:

UUID 不是属性列表的有效元素。您需要将其作为字符串存储在属性列表中,例如

“id”: id.uuidString as AnyObject

然后像这样转换回来:

id = UUID(uuidString: plist[“id”] as! String)!

【讨论】:

以上是关于为啥这个 plist 读/写失败?的主要内容,如果未能解决你的问题,请参考以下文章

fread()函数第一次读取成功,但第二次读取失败,为啥为啥为啥,

写/读 plist 文件 iPhone

boost async 读/写失败,“系统资源不足,无法完成请求的服务”

注册ocx文件时为啥报模块加载失败?

为啥在三元函数中分配给数组类型的表达式失败

Mobilefirst cli 构建失败:读取 info.plist 文件 1 字节 UTF-8