标签: nscoding

如何使用NSCoding加载Objective C Singleton?

我正在编写一个基本游戏,我使用的GameStateManager是一个单例并处理所有状态管理,例如保存,加载,删除方法.

我有一个单独的singelton处理所有的Game东西.游戏对象位于游戏状态管理器内部,因此我可以使用NSCoding和Archiving将其保存.

当我保存状态时,似乎没有问题,Game对象(单例)被正确保存.

但是,当我尝试加载状态(通过重新启动应用程序)时,游戏对象始终为null.

Strangley,如果我删除单例属性并使其成为标准类,这个问题就会消失,我可以加载类及其所有属性而不会出现任何重大问题.

总之,我这样做:

  1. GameStateManager = Singleton,处理所有游戏状态管理(加载,保存)并具有游戏对象(游戏)

  2. Game = Singleton,用于处理游戏中的事物并使用NSCoding协议.

  3. 用游戏对象保存游戏状态很好,对象显然就在那里.

  4. 加载游戏状态似乎使游戏对象为空.它应该存在,但由于某种原因它永远不会加载它.

  5. 如果我删除所有使游戏类成为singelton并使其成为正常类的属性,问题似乎就会消失.

我认为它与Game从未初始化的事实有关,但这没有意义,因为我可以在没有单例属性时加载游戏.

现在的代码如下.

// GameStateManager.m

-(void)saveGameState
{
    CCLOG(@"METHOD: saveGameState()");

    self.lastSaveDate   = [NSDate date];

    NSMutableData *data;
    NSString *archivePath = [NSTemporaryDirectory() stringByAppendingPathComponent:kGameSaveFile];
    NSKeyedArchiver *archiver;
    BOOL result;

    data = [NSMutableData data];
    archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];

    [archiver encodeObject:self.lastSaveDate forKey:@"lastSaveDate"];
    [archiver encodeObject:self.game forKey:@"game"];
    [archiver finishEncoding];
    result = [data writeToFile:archivePath atomically:YES];
    [archiver release];

}

-(void)loadGameState
{
    CCLOG(@"METHOD: loadGameState()");


    NSData *data;
    NSKeyedUnarchiver *unarchiver;
    NSString *archivePath = …
Run Code Online (Sandbox Code Playgroud)

singleton objective-c nscoding nskeyedarchiver

3
推荐指数
1
解决办法
2740
查看次数

处理Swift中的NSCoding错误

如何在Swift中处理与NSCoding相关的错误?

使用init?(coder:)它初始化对象时,如果数据无效,则可能无法初始化.我想抓住这些错误并妥善处理它们.为什么init?(coder:)在Swift中没有定义为抛出函数?

nscoding swift

3
推荐指数
1
解决办法
821
查看次数

转换为Swift 3打破了自定义类编码/解码

所以我刚刚将一个小应用程序从Swift 2.2转换为Swift 3.我已经摆脱了自动转换器后所需的通常错误和拖把,但我有一个运行时问题我无法工作出.

我有一个自定义类,我使用NSCoding协议保存到NSUserDefaults.当我尝试从NSUserDefaults解码编码对象时,它在行上失败,guard let duration = decoder.decodeObject(forKey: "duration") as? Int因为持续时间打印为nil.解码标题字符串工作正常,但至少编码函数的行正常工作.

这在2.2中运行良好,我找不到任何迹象表明Swift 3对NSCoding进行了更改.任何帮助将非常感激.

class TimerModel: NSObject, NSCoding, AVAudioPlayerDelegate {

    var name: String
    var active: Bool
    var paused: Bool
    var duration: Int
    var remainingWhenPaused: Int?
    var timerEndTime: Date?
    var timerStartTime: Date?
    var audioAlert: AlertNoise
    var UUID: String
    var colorScheme: BaseColor
    var alarmRepetitions: Int
    var timerRepetitions: Int
    var currentTimerRepetition: Int
    var audioPlaying: Bool
    var player: AVAudioPlayer = AVAudioPlayer()
    var countDownTimer: Timer = Timer()
    var delegate: timerProtocol? = nil

    init(withName name: …
Run Code Online (Sandbox Code Playgroud)

nsuserdefaults nscoding ios swift3

3
推荐指数
1
解决办法
1372
查看次数

无法在 Swift 中保存 Bool

我是 Swift 新手(C++ 背景),我正在尝试做一件非常简单的事情:保存 Bool。如果我将 bool 转换为“A”或“B”字符串,然后再转换回来,它会完美地工作,但如果我直接使用编码和 aDecoder 保存 bool,Bool 每次都会返回 nil。在互联网上找不到任何有关它的信息。

正如您在下面看到的,我只需用字符串替换 Bool 就可以了。

func boolwontsave(aBool:Bool) -> String {
    if aBool {
        return "A"
    }
    return "B"
}

func encode(with aCoder: NSCoder) {

    aCoder.encode(name, forKey: PropertyKey.name)
    aCoder.encode(number, forKey: PropertyKey.number)
    aCoder.encode(boolwontsave(aBool: ispresent), forKey: PropertyKey.present)

}

required convenience init?(coder aDecoder: NSCoder) {

    // The name is required. If we cannot decode a name string, the initializer should fail.
    guard let name = aDecoder.decodeObject(forKey: PropertyKey.name) as? String else {
        os_log("Unable to decode …
Run Code Online (Sandbox Code Playgroud)

nscoding swift

3
推荐指数
1
解决办法
1474
查看次数

使用 NSKeyedArchiver 归档自定义类时出现“无法写入数据,因为它的格式不正确”

我在 iOS12 中尝试了一个新的 API:

[NSKeyedArchiver archivedDataWithRootObject:<#(nonnull id)#> requiringSecureCoding:<#(BOOL)#> error:<#(NSError * _Nullable __autoreleasing * _Nullable)#>]
Run Code Online (Sandbox Code Playgroud)

我想做的很简单,归档一个自定义类,这里是代码:

一个名为 Cat 的类:

@interface Cat : NSObject <NSCoding>

@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSInteger age;

+ (void)saveThisCat:(Cat *)cat; 
+ (Cat *)getThisCat;

@end


@implementation Cat

- (void)encodeWithCoder:(nonnull NSCoder *)aCoder {
    [aCoder encodeObject:self.name forKey:@"name"];
    [aCoder encodeInteger:self.age forKey:@"age"];
}

- (nullable instancetype)initWithCoder:(nonnull NSCoder *)aDecoder {
    if (self = [super init]) {
        self.name = [aDecoder decodeObjectForKey:@"name"];
        self.age = [aDecoder decodeIntegerForKey:@"age"];
    }
    return self;
}

+ (void)saveThisCat:(Cat …
Run Code Online (Sandbox Code Playgroud)

objective-c nscoding nskeyedarchiver

3
推荐指数
1
解决办法
1621
查看次数

复制和序列化Quartz引用的最佳实践

我在Cocoa中有包含Quartz-2D参考(描述颜色,填充图案,渐变和阴影)的对象.我想NSCoding在我的对象中实现协议,因此需要序列化那些不透明的Quartz-2D结构.

可能的解决方案可能是

  • 在我的对象中定义一组属性,允许在需要时从头开始设置数据结构.那些可以很容易地序列化.示例:存储四个用于红色,绿色,蓝色和alpha的浮动,然后使用CGColorCreate.缺点:信息重复,因此潜在的一致性和(迄今为止微小的)空间消耗问题.我需要手动编写属性设置器,以便在组件发生更改时重新创建Quartz结构.这会大大增加我的代码.

  • 使用Quartz函数读出属性.例如:使用CGColorGetComponents的颜色.缺点:它似乎适用于颜色.但是没有其他结构的等效函数,所以我不知道它如何适用于渐变,阴影,阴影等.

  • 直接从原始的不透明结构中读出属性.缺点:正如文档所说,结构应该是不透明的.因此,如果发生了变化,我的代码就会破裂.(苹果当然不会提供像CGColorGetComponents应该这样做的功能.)此外,像CGFunctionRef内部的东西CGShadingRef真的会要求麻烦.

序列化Quartz结构的最佳实践是什么?

cocoa objective-c nscoding quartz-graphics

2
推荐指数
1
解决办法
828
查看次数

Game Center matchData的良好做法

我是GKTurnBasedMatch的新手,我正在试图找出在转弯期间玩家之间发送的"matchData"的良好做法.我发现的所有教程主要包括发送一串文本,我想发送更多.如果有人能给我一个更高级的教程,那就太好了.

我想做的一个例子就是战斗.这两个玩家有他们的化身,他们有不同的细节(健康,攻击,防御等),我该如何发送这些数据?我认为可能的唯一方法是将所有匹配细节(很多)编成NSDictionary并发送,以便它们可以再次放回到自定义匹配对象中.我应该实施NSCoding吗?

谢谢!

nscoding nsdata gamekit ios game-center

2
推荐指数
1
解决办法
1473
查看次数

如何自动实现属性和ivars的NSCoding

我试图将大量对象保存到文件中并检索它们以供以后使用.

以前,我使用过这些宏 - 虽然感觉很乏味.

然后我发现了自动编码,它以自己的方式很棒但它不能编码/解码实例变量.

我需要自动完成编码/解码的整个过程,因为我的应用程序仍在开发中,为每个ivar编写编码/解码实现是很繁琐的.

iphone xcode objective-c nscoding ios

2
推荐指数
1
解决办法
113
查看次数

如何使用NSCoding序列化C数组?


我有Objective-C类有C数组属性.
我想用NSCoding序列化该属性.

@interface TestClass : NSObject <NSCoding>
@property (nonatomic) int* intArray;
@end

@implementation TestClass
-(instancetype)init
{
    self = [super init];
    if (self) {
        _intArray = (int *)malloc(sizeof(int) * 5);
        for (int i = 0; i < 5; i++) {
            _intArray[i] = 0;
        }
    }
    return self;
}
-(void)dealloc
{
    free(_intArray);
}
-(instancetype)initWithCoder:(NSCoder *)coder
{
    self = [super init];
    if (self) {
        //???
    }
    return self;
}
-(void)encodeWithCoder:(NSCoder *)coder
{
    //???
}
@end
Run Code Online (Sandbox Code Playgroud)

我应该写什么?
谢谢.

编辑:
谢谢你的回答.
但是我应该使用decodeArrayOfObjCType:count:at:还是NSData?
如果我不知道数组的数量,我不能使用decodeArrayOfObjCType:count:at:method?

-(instancetype)initWithCoder:(NSCoder *)coder …
Run Code Online (Sandbox Code Playgroud)

objective-c nscoding

2
推荐指数
1
解决办法
819
查看次数

NSCoding:发现nil展开一个Optional值

自从更新到Swift 3后,我得到了这个非常知名的崩溃,我自己无法解决......:

致命错误:在解包可选值时意外发现nil*:

在线

self.isDefault = aDecoder.decodeObject(forKey: "BoxUserDefault_isDefault") as! Bool

为什么现在会崩溃?

这是我的课

class BoxUserDefault: NSObject, NSCoding {

    var frendlyName: String
    var hostname: String
    var isDefault: Bool

    init(frendlyName: String, hostname: String, isDefault: Bool) {
        self.frendlyName = frendlyName
        self.hostname = hostname
        self.isDefault = isDefault
        super.init()
    }

    func encode(with aCoder: NSCoder) {
        aCoder.encode(self.frendlyName, forKey: "BoxUserDefault_frendlyName")
        aCoder.encode(self.hostname, forKey: "BoxUserDefault_hostname")
        aCoder.encode(self.isDefault, forKey: "BoxUserDefault_isDefault")
    }

    required init?(coder aDecoder: NSCoder) {
        self.frendlyName = aDecoder.decodeObject(forKey: "BoxUserDefault_frendlyName") as! String
        self.hostname = aDecoder.decodeObject(forKey: "BoxUserDefault_hostname") as! String
        self.isDefault = aDecoder.decodeObject(forKey: "BoxUserDefault_isDefault") …
Run Code Online (Sandbox Code Playgroud)

nscoding swift

2
推荐指数
1
解决办法
652
查看次数