我正在编写一个基本游戏,我使用的GameStateManager是一个单例并处理所有状态管理,例如保存,加载,删除方法.
我有一个单独的singelton处理所有的Game东西.游戏对象位于游戏状态管理器内部,因此我可以使用NSCoding和Archiving将其保存.
当我保存状态时,似乎没有问题,Game对象(单例)被正确保存.
但是,当我尝试加载状态(通过重新启动应用程序)时,游戏对象始终为null.
Strangley,如果我删除单例属性并使其成为标准类,这个问题就会消失,我可以加载类及其所有属性而不会出现任何重大问题.
总之,我这样做:
GameStateManager = Singleton,处理所有游戏状态管理(加载,保存)并具有游戏对象(游戏)
Game = Singleton,用于处理游戏中的事物并使用NSCoding协议.
用游戏对象保存游戏状态很好,对象显然就在那里.
加载游戏状态似乎使游戏对象为空.它应该存在,但由于某种原因它永远不会加载它.
如果我删除所有使游戏类成为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) 如何在Swift中处理与NSCoding相关的错误?
使用init?(coder:)它初始化对象时,如果数据无效,则可能无法初始化.我想抓住这些错误并妥善处理它们.为什么init?(coder:)在Swift中没有定义为抛出函数?
所以我刚刚将一个小应用程序从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) 我是 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) 我在 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) 我在Cocoa中有包含Quartz-2D参考(描述颜色,填充图案,渐变和阴影)的对象.我想NSCoding在我的对象中实现协议,因此需要序列化那些不透明的Quartz-2D结构.
可能的解决方案可能是
在我的对象中定义一组属性,允许在需要时从头开始设置数据结构.那些可以很容易地序列化.示例:存储四个用于红色,绿色,蓝色和alpha的浮动,然后使用CGColorCreate.缺点:信息重复,因此潜在的一致性和(迄今为止微小的)空间消耗问题.我需要手动编写属性设置器,以便在组件发生更改时重新创建Quartz结构.这会大大增加我的代码.
使用Quartz函数读出属性.例如:使用CGColorGetComponents的颜色.缺点:它似乎适用于颜色.但是没有其他结构的等效函数,所以我不知道它如何适用于渐变,阴影,阴影等.
直接从原始的不透明结构中读出属性.缺点:正如文档所说,结构应该是不透明的.因此,如果发生了变化,我的代码就会破裂.(苹果当然不会提供像CGColorGetComponents应该这样做的功能.)此外,像CGFunctionRef内部的东西CGShadingRef真的会要求麻烦.
序列化Quartz结构的最佳实践是什么?
我是GKTurnBasedMatch的新手,我正在试图找出在转弯期间玩家之间发送的"matchData"的良好做法.我发现的所有教程主要包括发送一串文本,我想发送更多.如果有人能给我一个更高级的教程,那就太好了.
我想做的一个例子就是战斗.这两个玩家有他们的化身,他们有不同的细节(健康,攻击,防御等),我该如何发送这些数据?我认为可能的唯一方法是将所有匹配细节(很多)编成NSDictionary并发送,以便它们可以再次放回到自定义匹配对象中.我应该实施NSCoding吗?
谢谢!
我有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) 自从更新到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)