我正在尝试NSCodingswift中协议的基本实现,但似乎我无法成功地在对象被正确存档后取消归档.
这是我的尝试
import Cocoa
class User: NSObject, NSCoding {
var name: String
init(name: String) {
self.name = name
}
init(coder aDecoder: NSCoder!) {
self.name = aDecoder.decodeObjectForKey("name") as String
}
func encodeWithCoder(aCoder: NSCoder!) {
aCoder.encodeObject(name, forKey: "name")
}
}
let user = User(name: "Gabriele")
let encodedUser = NSKeyedArchiver.archivedDataWithRootObject(user)
let decodedUser = NSKeyedUnarchiver.unarchiveObjectWithData(encodedUser) as User
Run Code Online (Sandbox Code Playgroud)
在操场上运行它,它会在最后一行启动一个例外.这是细节
Execution was interrupted, reason: signal SIGABRT.
The process has been left at the point where it was interrupted, use "thread return -x" to return …Run Code Online (Sandbox Code Playgroud) 为什么 NSKeyedArchiver 性能这么差?与使用 NSArchiver 相比,大小翻了一番。
我正在使用以下行编码对象的 NSMutableArray
BOOL result = [NSArchiver archiveRootObject:self.appDataObject.materias toFile:archivePath];
Run Code Online (Sandbox Code Playgroud)
NSMutableArray 包含具有相应 encodeWithCoder 和 initWithCoder 的自定义对象
-(void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject: _fileName];
[aCoder encodeObject: _categoria];
[aCoder encodeObject: _materia];
[aCoder encodeObject: _nombre];
[aCoder encodeObject: _position];
[aCoder encodeValueOfObjCType:@encode(BOOL) at:&_favorite];
}
-(id)initWithCoder:(NSCoder *)aDecoder
{
if (self=[super init]) {
[self setFileName:[aDecoder decodeObject]];
[self setCategoria:[aDecoder decodeObject]];
[self setMateria:[aDecoder decodeObject]];
[self setNombre:[aDecoder decodeObject]];
[self setPosition:[aDecoder decodeObject]];
[aDecoder decodeValueOfObjCType:@encode(BOOL) at:&_favorite];
}
return self;
}
Run Code Online (Sandbox Code Playgroud)
它工作正常,因为它正确保存了文件,然后我可以取消归档它。它们大约有 3000 个对象,输出文件大约为900kB
当我将归档行更改为:
BOOL result = [NSKeyedArchiver archiveRootObject:self.appDataObject.materias …Run Code Online (Sandbox Code Playgroud) 在我的代码中的某个地方
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:someArray];
我希望data是nil,如果someArray是nil,但它返回一些数据,我不明白.
我把它打印出来如下
<62706c69 73743030 d4010203 0405080a 0b542474 6f705824 6f626a65 63747358 24766572 73696f6e 59246172 63686976 6572d106 0754726f 6f748000 a1095524 6e756c6c 12000186 a05f100f 4e534b65 79656441 72636869 76657208 11161f28 32353a3c 3e444900 00000000 00010100 00000000 00000c00 00000000 00000000 00000000 00005b>
我试图NSData *data = [NSKeyedArchiver archivedDataWithRootObject:nil];确保论证肯定是零.
我阅读了文档,但没有找到任何解释.
那究竟发生了什么?
编辑 我将数据写入文件,结果是这样的plist.它可能是NSKeyedArchiver存储对象的方式.

我有这个简单的课程
import UIKit
class SimpleModel: NSObject, NSCoding {
var name : String!
var done : Bool!
init(name:String) {
self.name = name
self.done = false
}
internal required init?(coder aDecoder: NSCoder) {
self.name = aDecoder.decodeObject(forKey: "name") as! String
self.done = aDecoder.decodeBool(forKey: "done") // BUG HERE
}
func encode(with encoder: NSCoder) {
encoder.encode(self.name, forKey: "name")
encoder.encode(self.done, forKey: "done")
}
}
Run Code Online (Sandbox Code Playgroud)
保存代码:
let data = NSKeyedArchiver.archivedData(withRootObject: storageArray)
UserDefaults.standard.set(data, forKey: "storage")
UserDefaults.standard.synchronize()
Run Code Online (Sandbox Code Playgroud)
读取代码:
if let data = UserDefaults.standard.data(forKey: "storage") {
storageArray = NSKeyedUnarchiver.unarchiveObject(with: data) …Run Code Online (Sandbox Code Playgroud) 当尝试在 iOS swift 中对我的自定义对象进行编码时,从 Xcode 8.3 获取此错误
无法识别的选择器发送到实例 0x60800166fe80 *** -[NSKeyedArchiver dealloc]:警告:NSKeyedArchiver 在没有调用 -finishEncoding 的情况下被释放。
我的代码是这样的:
导入 UIKit 导入基础
class Place: NSObject {
func setCustomObject(CustomObject obj:Any,Key key:String) {
let encodedObject : Data = NSKeyedArchiver.archivedData(withRootObject: obj)
UserDefaults.standard.set(encodedObject, forKey: key)
}
}
Run Code Online (Sandbox Code Playgroud) 该文件是在Objective-C中的旧项目中创建的.
NSKeyedArchiver* archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:dataForWrite];
[archiver encodeObject:dictVer forKey:@"cityVersionDict"];
[archiver finishEncoding];
BOOL flag = [dataForWrite writeToFile:path atomically:YES];
Run Code Online (Sandbox Code Playgroud)
我想通过以下代码在Swift4.0中的新项目中读取此文件:
do {
let data = try Data.init(contentsOf: path)
} catch {
print(error)
}
Run Code Online (Sandbox Code Playgroud)
然后捕获错误:错误Domain = NSCocoaErrorDomain Code = 256"无法打开文件"cityVersionDict.archiver"." 的UserInfo = {NSURL = /用户/ SAM /库/开发商/ CoreSimulator /设备/ 51CD0088-EE62-4ED0-8660-4C6486BC7823 /数据/容器/数据/应用/ 5740ADE1-4930-4968-B86F-7E2F5F99F5F8 /库/缓存/ cityVersionDict.archiver}
在Objective-C中,这个文件可以正常读取.我已经仔细检查了路径是否正确.但仍然遇到错误.请帮忙,谢谢
let lessons = Lessons(definition: "testo", photo: url)
SaveUtil.saveLessons(lessons: lessons!)
let x = SaveUtil.loadLessons()
Run Code Online (Sandbox Code Playgroud)
所以一切都编译并运行,但 x 为零......我试图使这个 ios12/swift 4.2 兼容,但不知道缺少什么。谢谢!
class SaveUtil {
static func saveLessons(lessons: Lessons) {
let data = try! NSKeyedArchiver.archivedData(withRootObject: lessons, requiringSecureCoding: false)
UserDefaults.standard.set(data, forKey: "lessons")
}
static func loadLessons() -> [Lessons]? {
let data = UserDefaults.standard.data(forKey: "lessons")
return try! NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data!) as? [Lessons]
}
}
Run Code Online (Sandbox Code Playgroud) 请帮我!我陷入了困境,找不到出路。我正在尝试学习IOS编程工作,所以我想我将从他们的教程应用“ Meal list”应用开始。我现在应该开始保存持久性数据,现在编辑器使我陷入了永无休止的循环。我有一行代码...
let isSuccessfulSave = NSKeyedArchiver.archiveRootObject(meals, toFile: Meal.ArchiveURL.path)
Run Code Online (Sandbox Code Playgroud)
那给了我一个警告,说...
在iOS 12.0中不推荐使用'archiveRootObject(_:toFile :)':使用+ archivedDataWithRootObject:requiringSecureCoding:error:代替
好的,所以我将代码行更改为...
let isSuccessfulSave = NSKeyedArchiver.archivedDataWithRootObject(meals)
Run Code Online (Sandbox Code Playgroud)
然后给我警告...
'archivedDataWithRootObject'已重命名为'archivedData(withRootObject :)'
好的,所以我将代码行更改为...
let isSuccessfulSave = NSKeyedArchiver.archivedData(withRootObject: meals)
Run Code Online (Sandbox Code Playgroud)
告诉我...
在iOS 12.0中不推荐使用'archivedData(withRootObject :)':使用+ archivedDataWithRootObject:requiringSecureCoding:error:代替
好的...所以...不建议使用archivedData,而我必须使用archivedDataWithRootObject,但是使用archivedDataWithRootObject已重命名为archivedData,但是不建议使用archivedData,所以请使用archivedDataWithRootObject,将其重命名为archivedData,不建议使用... ad infinitum。
我试过看开发人员文档,但是他们只是告诉我同样的事情,一个已经过时,没有链接或任何东西,搜索google只是给了我一堆页面,向我展示了使用其中任何一个的语法。我仍然对IOS编程真的很陌生,不知道如何摆脱这种无休止的循环,从重命名到重命名到...
请帮助,我迷路了,不确定如何继续。谢谢。
我在移动电话上存储了一些医疗保健数据,我想知道最好的加密系统是什么,以保证数据的安全.它基本上是一堆模型对象,我正在使用NSKeyedArchiver进行序列化和存储/ Blackberry上的等价物(现在这个名字不在我身边)
有小费吗?我不想像我一样编写安全协议,但其他一个线程提出了以下方法.
有更标准的方法吗?
谢谢,
Teja.
编辑:我很感激您正试图帮助我,但目前正在讨论的事情是业务层面的讨论,我无法控制.所以重新解释我的问题,如果你忽略它是医疗数据,但是一些机密数据,比如说密码,你会怎么做呢?
我需要能够比较使用NSKeyedArchiver创建的plist文件的两个版本.特别是,它是在Xcode中为.xcdatamodeld文件创建的"元素"文件.
由于我自己没有创建此文件,因此无法重新创建其对象模型.相反,我需要了解归档包含哪些类和键控属性.
理想情况下,我想创建一个包含表示类名称及其属性名称和值的字符串的树.我假设所有这些信息都存储在存档中,因此应该可以一般地解析这个存档,对吧?
我已经阅读了有关NSKeyedUnarchiver及其代理人的信息.我只是这样:
取消归档文件数据:
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
unarchiver.delegate = self;
id graph = [unarchiver decodeObjectForKey:@"root"];
Run Code Online (Sandbox Code Playgroud)
这是在请求未知类时调用的委托方法.我在这里返回一个代理类,我希望在其中收集它的值:
- (Class)unarchiver:(NSKeyedUnarchiver *)unarchiver cannotDecodeObjectOfClassName:(NSString *)name originalClasses:(NSArray *)classNames
{
NSLog(@"wants: %@", name);
return [ObjProxy class];
}
Run Code Online (Sandbox Code Playgroud)
代理类实现
- (id)initWithCoder:(NSCoder *)aDecoder
Run Code Online (Sandbox Code Playgroud)
其中我不知道如何继续,不知道类的实际属性.NSCoder似乎没有提供任何功能来了解可用的密钥.是否有一个技巧可以通过覆盖一些较低级别的objc方法来获取它们?
到目前为止,通过上面显示的这个小代码,在解析"elements"文件时,我只获得了一个类"XDPMModel"的请求,然后就完成了.
任何想法如何使这个工作,即更深入地穿越树?
nskeyedarchiver ×10
ios ×5
swift ×4
iphone ×2
objective-c ×2
boolean ×1
cocoa ×1
cocoa-touch ×1
core-data ×1
dealloc ×1
encode ×1
encryption ×1
nscoder ×1
nscoding ×1
nsdata ×1
persistence ×1
plist ×1
swift4 ×1
xcode ×1