我在写一个名为Packet的对象时得到了以下代码,并通过Multipeer连接发送到另一端.但是,每当它尝试解码编码对象时,我都会收到以下错误.
class Packet : NSObject, NSCoding {
var tmp1: Double = 0
var tmp2: Double = 0
struct PropertyKey {
static let tmp1Key = "tmp1Key"
static let tmp2Key = "tmp2Key"
}
init(tmp1: Double, tmp2: Double) {
self.tmp1 = tmp1
self.tmp2 = tmp2
super.init()
}
deinit {
}
required convenience init(coder aDecoder: NSCoder) {
debugPrint("initcoder")
let tmp1 = aDecoder.decodeObject(forKey: PropertyKey.tmp1Key) as! Double // crash here
let tmp2 = aDecoder.decodeObject(forKey: PropertyKey.tmp2Key) as! Double
self.init(tmp1: tmp1, tmp2: tmp2)
}
public func encode(with aCoder: …Run Code Online (Sandbox Code Playgroud) 当我使用存储属性创建UIView或创建子类时UIViewController,Xcode 不会编译我的项目,除非我包含required init?(coder aDecoder: NSCoder). 目前,我有以下实现来关闭编译器:
required init?(coder aDecoder: NSCoder) {
fatalError()
}
Run Code Online (Sandbox Code Playgroud)
我明白为什么我需要包含这个初始化程序;我的子类需要符合NSCoding协议,因为它的超类符合它,并且这个初始化器是NSCoding协议的一部分,所以它需要与我的类一起工作,即初始化我的类的所有存储属性(初始化器的超类版本会赢)做)。
我想一个正确的实现应该是这样的:
class MyView: UIView {
let label: UILabel
override init(frame: CGRect) {
label = UILabel()
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
if let label = aDecoder.decodeObject() as? UILabel {
self.label = label
} else {
return nil
}
super.init(coder: aDecoder)
}
override func encode(with aCoder: NSCoder) {
aCoder.encode(label)
super.encode(with: aCoder)
}
}
Run Code Online (Sandbox Code Playgroud)
但是,考虑到我的应用程序有 50 …
我正在尝试编码地图上的注释,但我读到我无法对CLLocationcoordinate2D变量进行编码.有谁知道我怎么解决这个问题?这是一些代码.
这是我放下引脚的地方:
- (void)press:(UILongPressGestureRecognizer *)recognizer {
CGPoint touchPoint = [recognizer locationInView:_worldView];
CLLocationCoordinate2D touchMapCoordinate = [_worldView convertPoint:touchPoint toCoordinateFromView:_worldView];
geocoder = [[CLGeocoder alloc]init];
CLLocation *location = [[CLLocation alloc]initWithCoordinate:touchMapCoordinate
altitude:CLLocationDistanceMax
horizontalAccuracy:kCLLocationAccuracyBest
verticalAccuracy:kCLLocationAccuracyBest
timestamp:[NSDate date]];
[geocoder reverseGeocodeLocation:location
completionHandler:^(NSArray *placemarks, NSError *error) {
//NSLog(@"reverseGeocoder:completionHandler: called");
if (error) {
//NSLog(@"Geocoder failed with error: %@", error);
} else {
CLPlacemark *place = [placemarks objectAtIndex:0];
geocodedAddress = [NSString stringWithFormat:@"%@ %@, %@ %@", [place subThoroughfare], [place thoroughfare], [place locality], [place administrativeArea]];
if (UIGestureRecognizerStateBegan == [recognizer state]) {
value = …Run Code Online (Sandbox Code Playgroud) 我的问题: saveInBackground没有用.
原因它不起作用:我将PFObjects存储在NSArray中保存到文件使用NSKeyedArchiving.我这样做的方法是NSCoding通过这个库实现.由于某些我不知道的原因,正在添加其他几个字段并将其设置为NULL.我有一种感觉,这是搞砸了API调用saveInBackground.当我调用saveInBackground第一组对象(之前NSKeyedArchiving)saveInBackground工作正常.但是,当我在第二个对象(之后NSKeyedArchiving)上调用它时,它不会保存.为什么是这样?
保存
[NSKeyedArchiver archiveRootObject:_myArray toFile:[self returnFilePathForType:@"myArray"]];
Run Code Online (Sandbox Code Playgroud)
恢复
_myArray = (NSMutableArray *)[NSKeyedUnarchiver unarchiveObjectWithFile:
[self returnFilePathForType:@"myArray"]];
Run Code Online (Sandbox Code Playgroud)
NSArchiving之前的对象
2014-04-16 16:34:56.267 myApp[339:60b]
<UserToMessage:bXHfPM8sDs:(null)> {
from = "<PFUser:sdjfa;lfj>";
messageText = "<MessageText:asdffafs>";
read = 0;
to = "<PFUser:asdfadfd>";
}
2014-04-16 16:34:56.841 myApp[339:60b]
<UserToMessage:bXHsdafdfs:(null)> {
from = "<PFUser:eIasdffoF3gi>";
messageText = "<MessageText:asdffafs>";
read = 1;
to = "<PFUser:63sdafdf5>";
}
Run Code Online (Sandbox Code Playgroud)
NSArchiving之后的对象
<UserToMessage:92GGasdffVQLa:(null)> {
ACL = "<null>";
createdAt …Run Code Online (Sandbox Code Playgroud) 当使用我的类初始化我的类的实例时NSCoding,我想用Core Data数据库中的现有对象替换它而不是调用:
super.init(entity: ..., insertIntoManagedObjectContext: ...)
Run Code Online (Sandbox Code Playgroud)
因为那会将新对象插入数据库.
class MyClass: NSManagedObject, NSCoding {
required init(coder aDecoder: NSCoder) {
// Find a preexisting object in the Core Data database
var ctx = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext!
var fs = NSFetchRequest(entityName: "MyClass")
// ... Configure the fetch request based on values in the decoder
var err: NSErrorPointer = nil
var results = ctx.executeFetchRequest(fs, error: err)
// ... Error handling, etc
newObject = results[0] as! MyClass
// Attempt to …Run Code Online (Sandbox Code Playgroud) 我有一个小应用程序,具有一些保存功能.我有一个名为:Closet的数据模型类:
class Department: NSObject, NSCoding {
var deptName = ""
var managerName = ""
var Task: [Assignment]? // <----- assignment class is in example 2
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(deptName, forKey: "deptName")
aCoder.encodeObject(managerName, forKey: "mngName")
// aCoder.encodeObject(Task, forKey: "taskArray")
}
required init(coder aDecoder: NSCoder) {
super.init()
course = aDecoder.decodeObjectForKey("deptName") as! String
instructor = aDecoder.decodeObjectForKey("mngName") as! String
// Task = aDecoder.decodeObjectForKey("tasKArray") as? [Assignment]
}
override init() {
super.init()
}
}
Run Code Online (Sandbox Code Playgroud)
因此,这是主控制器数据模型,在第一个View Controller中,用户可以点击"+"按钮添加部门名称和管理员名称.问题不在于保存这个,因为我使用NSKeyedArchive成功保存并在应用程序启动时将其加载回来.
问题:
我想在这个名为Assignment的数据模型部门添加一个赋值数组,它有一个title和一个notes变量.这是作业的数据模型: …
我有这个枚举:
typedef types {
HBIntineraryTypeVisited = 0,
HBIntineraryTypeUnvisited,
HBIntineraryTypeUnknown,
HBIntineraryTypeDeleted,
} HBIntineraryType;
Run Code Online (Sandbox Code Playgroud)
并希望使用nscoding协议将其与其他一些变量一起存储
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self) {
_name = [aDecoder decodeObjectForKey:@"name"];
// todo decode enum object
}
}
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:_name forKey:@"name"];
// todo encode enum object
}
Run Code Online (Sandbox Code Playgroud)
我使用什么编码器方法来解码和编码这种枚举?
从我的应用程序中保存少量数据时,最好使用NSUserDefaults或NSCoding?现在我使用NSCoding(encodeWithCoder/initWithCoder等),但似乎NSUserDefaults可能更简单.我的总数据是关于各种Ints/Strings/MutableArray,总共只有几十个.
我决定使用NSSecureCoding它NSCoding,但我无法让它工作.
我希望以下代码失败,因为我正在编码NSString但尝试解码NSNumber.但是,初始化对象时不会抛出异常.
+ (BOOL)supportsSecureCoding
{
return YES;
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
// prints '1' as expected
NSLog(@"%d", coder.requiresSecureCoding);
// unexpectedly prints 'foo' (expecting crash)
NSLog(@"%@", [coder decodeObjectOfClass:NSNumber.class forKey:@"bar"]);
return [super init];
}
- (void)encodeWithCoder:(NSCoder *)coder
{
[coder encodeObject:@"foo" forKey:@"bar"];
}
Run Code Online (Sandbox Code Playgroud)
这是我用来测试上面代码片段的代码:
MyClass *object = [[MyClass alloc] init];
NSMutableData *const data = [[NSMutableData alloc] init];
NSKeyedArchiver *const archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
archiver.requiresSecureCoding = YES;
[archiver encodeObject:object forKey:@"root"];
[archiver finishEncoding];
NSKeyedUnarchiver *const …Run Code Online (Sandbox Code Playgroud) 我见过几个类似于我的问题; 然而,那些与swift 2/1有关,我目前正在使用swift 3.我相信Apple已经稍微改变了它.
class Person: NSObject, NSCoding {
var signature: UIImage
init(signature: UIImage) {
self.signature = signature
}
required convenience init(coder aDecoder: NSCoder) {
let signature = aDecoder.decodeObject(forKey: "signature") as! UIImage
self.init(signature: signature)
}
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encode(signature, forKey: "signature")
}
}
Run Code Online (Sandbox Code Playgroud)
你会注意到Swift 3现在如何强迫我使用required convenience init(而不是required init(.也许这与它有关.
我该如何解决这个问题?谢谢!