我如何使用-[NSCoder encodeBytes:length:]和-[NSCoder decodeBytesWithReturnedLength:]双倍?
我有一个符合NSCoding两个double属性的对象,我目前正在使用NSNumber编码/解码值:
- (id)initWithCoder:(NSCoder *)decoder
{
if (!(self = [super init]))
return nil;
latitude = [(NSNumber *)[decoder decodeObject] doubleValue];
longitude = [(NSNumber *)[decoder decodeObject] doubleValue];
return self;
}
- (void)encodeWithCoder:(NSCoder *)coder
{
[coder encodeObject:[NSNumber numberWithDouble:latitude]];
[coder encodeObject:[NSNumber numberWithDouble:longitude]];
}
Run Code Online (Sandbox Code Playgroud)
然而,这给了我不可接受的性能(用我的测试数据解码6秒,这比生产数据小得多).
如果我使用密钥,我可以使用-encodeDouble:forKey:,但我没有使用密钥(它们很慢),而且与Mac OS X不同-encodeDouble:,iOS上没有方法.
所以,我需要使用encodeBytes:length:和decodeBytesWithReturnedLength:,但我的C能力非常有限.我不确定如何在void *和之间进行转换double.
我有一个实施的问题子类来NSView实现NSCoding.
似乎声明init(coder: NSCoder)在NSView和中是冲突的NSCoding.
NSView如今说它可以使用,但NSCoding仍然说它是不可用的.
当我尝试覆盖init(coder: NSCoder)并执行自定义初始化时,Xcode 6.1给出了一条错误消息:
一个不可用的初始化程序无法链接到用'init?'编写的可用初始化程序'init(coder :)'
我该如何做我班级的自定义初始化?
这是一个愚蠢的例子,我扩展了一个视图,我想为我的视图保留一个额外的点击计数器.
import Cocoa
import Foundation
class MyView: NSView, NSCoding {
var clickCounter:Int = 0
required init(coder: NSCoder) {
super.init(coder: coder)
coder.encodeObject(self.clickCounter,
forKey: "clickCounter")
}
override func encodeWithCoder(coder: NSCoder) {
super.encodeWithCoder(coder)
coder.encodeObject(self.clickCounter, forKey: "clickCounter")
}
override func mouseDown(theEvent: NSEvent) {
clickCounter++
}
}
Run Code Online (Sandbox Code Playgroud)

为什么能够编码数组Int使用aCoder.encodeObject(myIntArray, forKey: "myKey"),但是你想编码的数组时,编译器错误UInt8值?转换实际上并不是戏剧性的,但我会有56个不必要的Bits来编码......
从 NSKeyedArchiver 获取崩溃
2016-10-06 17:06:06.713 MessagesExtension[24473:2175316] *** NSForwarding:
warning: object 0x61800009d740 of class '' does not implement
methodSignatureForSelector: -- trouble ahead
Unrecognized selector -[MessagesExtension.Model replacementObjectForKeyedArchiver:]
Run Code Online (Sandbox Code Playgroud)
我创建了一个名为Coding的协议,其全部目的是简化NSCoding和NSKeyedArchiver,而无需使用 Objective-C 的片段。
protocol Coding {
static var directory: FileManager.SearchPathDirectory { get }
static var domainMask: FileManager.SearchPathDomainMask { get }
func encode() -> [String: AnyObject]
init()
init?(dict: [String: AnyObject]?)
}
extension Coding {
static var directory: FileManager.SearchPathDirectory {
return .documentDirectory
}
static var domainMask: FileManager.SearchPathDomainMask {
return .userDomainMask
} …Run Code Online (Sandbox Code Playgroud) 在decodeDouble上NSCoder返回一个非可选值,但我想,以确定一个值是否是零它编码之前.
这是我的情景:
var optionalDouble: Double? = nil
func encode(with aCoder: NSCoder) {
if let optionalDouble {
aCoder.encode(optionalDouble, forKey: "myOptionalDouble")
}
}
convenience required init?(coder aDecoder: NSCoder) {
optionalDouble = aDecoder.decodeDouble(forKey: "myOptionalDouble")
// here optionalDouble is never nil anymore
}
Run Code Online (Sandbox Code Playgroud)
因此0,如果从未设置值,则解码double会返回,因此我似乎无法确定值是实际0还是nil在编码之前
有没有办法在编码之前检查双精度是否为零?
我正在使用 ARKit 和 GameKitMatches,所以我不能使用 Codable (afaik),因为MCPeerID它也是ARWorldMap不可编码的,首先要解决这个问题。
所以我使用 NSCoding 和 NSSecureCoding 但由于某种原因我总是发现错误:
The data couldn’t be read because it isn’t in the correct format.
...即使我真的只是创建了它。我也尝试使用,NSKeyedUnarchiver.unarchivedObject(ofClasses: classes但这在我的初始化中抛出了一个意外的零。
这是我制作的一个显示问题的游乐场:
class CodingData: NSObject, NSCoding, NSSecureCoding {
static var supportsSecureCoding = true
var dic: [String: Int]!
var i: Int!
func encode(with coder: NSCoder) {
coder.encode(i, forKey: "i")
coder.encode(dic, forKey: "dic")
}
required convenience init?(coder: NSCoder) {
let anInt = coder.decodeObject(forKey: "i") as! Int
let anDic = coder.decodeObject(forKey: "dic") as! …Run Code Online (Sandbox Code Playgroud) 所以我把这个自定义对象称为'Box',它正在抛出那个错误.我的NSDictionary里面是......
box = [[Box alloc] initWithHeight:20 height:40];
wrap.dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:numberInt, kInt, numberShort, kShort, numberLong, kLong, numberFloat, kFloat, numberDouble, kDouble, numberBool, kBool, nsString, kString, nsDate, kDate, box, @"keybox", nil];
Run Code Online (Sandbox Code Playgroud)
请注意我在顶部创建的框对象,并在最后添加到NSDictionary中.在盒子不在那里之前,一切正常,但是当我添加自定义对象'Box'时,它无法再保存.
- (void) saveDataToDisk:(NSMutableDictionary *)dictionaryForDisk
{
NSMutableData *data = [NSMutableData data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];
//Encode
[archiver setOutputFormat:NSPropertyListBinaryFormat_v1_0];
[archiver encodeObject:dictionaryForDisk forKey:@"Dictionary_Key"];
[archiver finishEncoding];
[data writeToFile:[self pathForDataFile] atomically:YES];
}
- (NSString *) pathForDataFile {
NSArray* documentDir = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString* path = nil;
if (documentDir)
{
path = [documentDir objectAtIndex:0];
} …Run Code Online (Sandbox Code Playgroud) 当用户第一次启动应用程序时,他会弹出一个并且必须保存图像.它适用于模拟器和4S.但是当我用我的3G开始它时,一旦我选择了一张照片就会给我一个SIGABRT错误.我假设它是因为图片的大小过于挑选并因此声称所有的公羊 - 但这是相当奇怪的,因为我把它做得更小.这是代码:
- (void)viewDidLoad
{
[super viewDidLoad];
if ([[NSUserDefaults standardUserDefaults] objectForKey:@"bild"] == nil) {
picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
[self presentModalViewController:picker animated:YES];
}
}
- (void)imagePickerController:(UIImagePickerController *) Picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
double compressionRatio=1;
NSData *imageData=UIImageJPEGRepresentation([info objectForKey:@"bild"],compressionRatio);
while ([imageData length]>5000) {
compressionRatio=compressionRatio*0.20;
imageData=UIImageJPEGRepresentation([info objectForKey:@"bild"],compressionRatio);
}
UIImage *yourUIImage;
yourUIImage = [info objectForKey:UIImagePickerControllerOriginalImage];
imageData = [NSKeyedArchiver archivedDataWithRootObject:yourUIImage];
[[NSUserDefaults standardUserDefaults] setObject:imageData forKey:@"bild"];
[[NSUserDefaults standardUserDefaults] synchronize];
[self dismissModalViewControllerAnimated:YES];
}
Run Code Online (Sandbox Code Playgroud)
我在此行得到SIGABRT错误imageData = [NSKeyedArchiver archivedDataWithRootObject:yourUIImage];
我应该使用其他方法来调整图像大小吗?或者我应该将其保存为本地文件并在应用程序启动时检索它?(如果它是可能的)
NSCoding和NSCopying在低级别上有什么真正的区别?
它们是应该独立使用,还是什么时候使用哪一个?
我有一个class对象,该对象SGBContainer具有一个名为class 的数组objects,其中包含class对象SGBObject。当前,它们各自实现NSCoding,但不实现NSSecureCoding。在-initWithCoder:为SGBContainer这个样子的:
- (id)initWithCoder:(NSCoder *)aCoder
{
self = [self init];
if (self)
{
_objects = [aCoder decodeObjectForKey:@"objects"];
}
}
Run Code Online (Sandbox Code Playgroud)
我想切换为使用NSSecureCoding,据我所知,这意味着将上述内容更改为:
- (id)initWithCoder:(NSCoder *)aCoder
{
self = [self init];
if (self)
{
_objects = [aCoder decodeObjectOfClass:[NSArray class] forKey:@"objects"];
}
}
Run Code Online (Sandbox Code Playgroud)
...没有太大的改进,因为无论其类如何,数组的内容都会被实例化。如何确保数组仅包含类对象SGBObject而不实例化它们?