我在Obj-C中做了很多NSCoding归档,但我不确定它如何处理Swift中的结构,也不确定具有可选值的数组.这是我的代码:
public struct SquareCoords {
var x: Int, y: Int
}
Run Code Online (Sandbox Code Playgroud)
这是我需要存储的类:
public class Player: NSCoding {
var playerNum: Int
var name = ""
private var moveHistory: [SquareCoords?] = []
init (playerNum: Int, name: String) {
self.playerNum = playerNum
self.name = name
}
public required init(coder aDecoder: NSCoder!) {
playerNum = aDecoder.decodeIntegerForKey("playerNumKey")
name = aDecoder.decodeObjectForKey("nameKey") as String
moveHistory = aDecoder.decodeObjectForKey("moveHistoryKey") as [SquareCoords?]
}
public func encodeWithCoder(aCoder: NSCoder!) {
aCoder.encodeInteger(playerNum, forKey: "playerNumKey")
aCoder.encodeObject(name, forKey: "nameKey")
aCoder.encodeObject(moveHistory, forKey: "moveHistoryKey")
}
...
Run Code Online (Sandbox Code Playgroud)
在编码器init的最后一行,我在XCode中收到以下错误消息: …
是否可以使用?编码Objective-C块NSKeyedArchiver?
我不认为Block对象是NSCoding-compliant,因此[coder encodeObject:block forKey:@"block"]不起作用?
有任何想法吗?
FooBar下面的类必须覆盖==该Equatable类型的功能.
但是,调用对象contains数组FooBar不会导致==调用自定义函数内的断点.是否可能其他==功能覆盖此自定义功能?
注意:因为FooBar必须从NSCoding和NSObject继承,所以FooBar不会将Equatable列为协议,因为它会导致此错误:
'FooBar'与协议'Equatable'的冗余一致性
func ==(lhs: FooBar, rhs: FooBar) -> Bool {
return lhs.id == rhs.id
}
class FooBar: NSObject, NSCoding {
// Class def
}
// Both serverFooBars and gFooBars are [FooBar]
let newFooBars = serverFooBars.filter { !gFooBars.contains($0) }
Run Code Online (Sandbox Code Playgroud) 我想扩展一个框架类(我不想直接编辑源代码),并使其符合NSCoding.
基本上,这是我所处的情况的简化:
/* Can't be edited. */
class Car: NSObject {
var color: String?
}
/* Can be edited */
extension Car: NSCoding {
init(coder aDecoder: NSCoder) {
}
func encodeWithCoder(aCoder: NSCoder) {
}
}
Run Code Online (Sandbox Code Playgroud)
问题是init(coder aDecoder: NSCoder),根据头文件,a designated initializer(这不是很奇怪吗?不应该是convenience initializer?).但是,文档说扩展无法添加新的指定初始化程序.
我的英语不完美,也许我错过了一些东西......或者它真的不可能?
我知道当你编写实现NSCoding的对象的子类的initWithCoder方法时,你必须调用super initWithCoder(而不是super init),但是我必须调用super encodeWithCoderencodeWithCoder的实现吗?
我在String中有一个实例变量名
var name: String
Run Code Online (Sandbox Code Playgroud)
我的类实现了NSCoding协议.所以我的名字
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(self.name, forKey: kName)
}
required init(coder aDecoder: NSCoder) {
self.name = aDecoder.decodeObjectForKey(kName) as String // CRASH HERE
}
Run Code Online (Sandbox Code Playgroud)
结果?我在使用解码器启动时遇到了运行时崩溃.我将init更改为:
var temp = aDecoder.decodeObjectForKey(kName) as NSString!
self.name = aDecoder.decodeObjectForKey(kName) as String
Run Code Online (Sandbox Code Playgroud)
并意识到值temp保持正确的NSString值.所以我认为下面的行将解决它,但它会发出一个链接器错误:
self.name = aDecoder.decodeObjectForKey(kName) as NSString!
Run Code Online (Sandbox Code Playgroud)
问题是如何采取临时措施并将其命名?
理想情况下,NSCoding兼容类将使用encodeWithCoder:和initWithCoder按预期工作:(至少我认为直到最近),开发人员不必担心例程内部的内容(除非我对NSCoding兼容类的想法完全搞砸了) !)
UIImageView类符合NSCoding.所以我不应该打扰如何使用NSKeyedArchiver和NSKeyedUnarchiver类对它进行序列化/反序列化.但每次我尝试编码UIImageView对象时,都会收到UIImage无法识别的错误:encodeWithCoder:method.
现在UIImageView内部使用UIImage对象.但编码是否应该自己处理?
或者文档中指定的NSCoding合规性是否让用户知道他们可以实现initWithCoder和encodeWithCoder方法?
有人可以帮我澄清一下!我很困惑!
A有一些NSValue(通过KVC获得valueForKey)我需要附加到一个NSData对象,以便使用Game Center通过网络发送它.显然,我还需要将NSValue背面转换NSData为更多的KVC(setValue:forKey:).
我不知道每一个确切的类型NSValue,所以我仅限于使用所提供的接口NSValue和NSData.我应该提一下,NSValue它们永远不是指针类型.
我很惊讶没有[NSData dataWithValue:value],也没有[value dataWithEncoding:]类似的东西.但也许我是盲目的,没有看到明显的选择.我考虑过使用getValue:将值复制到void*缓冲区中,但除了使用objCType并将其与所有可能的类型进行比较之外,我应该如何确定缓冲区长度?
我该怎么办呢?
注意:
NSKeyedArchiver这是不可能的,因为它非常低效.4字节浮点数归档为142字节NSData,8字节CGPoint归档时使用260字节NSData.将发送的数据量保持在最低限度对我正在做的事情至关重要.
我在写一个名为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 …