将带有字符串和 NSImage 属性的 Class 导出到文件

Export Class with String & NSImage Properties to File

我有一个 class,我希望能够将其打开并导出到文件中。它不需要编辑 - 这只是一种与我的应用程序的其他用户共享部分对象 CoreData 数据库的方法,所以我认为我不需要 subclassing NSDocument 的复杂性.

class 非常基本,有两个属性 String 和一个 NSImage 的文件名,它引用应用程序沙箱中的图像。

最初,我想到了使用文档包,基本上是一个包含图像的文件夹(如果需要)和一个包含字符串和图像文件名的 plist。 现在,我倾向于创建一个 class-just-for-export-and-import,它使用 NSCoding 将图像和字符串保存到文件中。

以下是我不确定的内容:

我研究过了!有很多关于保存图像或保存 NSDocument 的信息,但我只是想为用户提供一种简单的方法来 将任意数据导出和导入 到我的或从中导出应用程序的核心数据存储。

任何一个选项都应该可以正常工作。如果您选择 NSCoding 路线,请务必使用键控存档器。

任何一个选项都可以处理一个对象数组,你只需要设计你的文件结构/处理代码来检查和处理它。

对于文件选项,图像将只是磁盘上的图像。对于编码选项,所有内容都将是磁盘上的二进制数据,但这是在编码过程中完成的(您将在此处将图像转换为数据)。

根据文件的结构,这可能是包中文件的扩展名。对于编码选项,它是键名。

您的两个选项对于用户来说实际上是相同的,并且将来可以扩展,您选择哪个取决于个人喜好。我希望编码选项更快更容易编写代码。

实施 NSCoding 协议,您可以轻松共享您描述的对象。

public required init!(coder:NSCoder)
{
    self.busStopName = coder.decodeObjectForKey("busStopName") as? String
    self.busStopID = coder.decodeIntegerForKey("busStopID") as Int
    let lines: [String]! = coder.decodeObjectForKey("busLines") as? [String]
    let photo: NSData = coder.decorDataForKey("photo") as? NSData
}

public override func encodeWithCoder(encoder: NSCoder) -> Void
{
    encoder.encodeObject(self.busStopName, forKey:"busStopName")
    encoder.encodeInteger(self.busStopID, forKey: "busStopID")
    encoder.encodeObject(self.busLines, forKey: "busLines")
    encoder.encodeDataObject(self.busStopImage, forKey: "photo")
}

为了从 NSData 创建一个 UIImage 使用这个 initializer

let image: UIImage = UIImage(data: <the nsdata decoded>)

并使用此 UIKit 函数之一从 UIImage 获取 NSData

UIImageJPEGRepresentation(::) UIImagePNGRepresentation(_:)

使用 NSCoding 你可以保存每一个 class 内置支持这个协议的或者你自己添加的。 NSImage 和 – 当然 – NSString 都符合 NSCoding。您只需为您的自定义 class、which is pretty simple:

添加 NSCoding 支持
- (void)encodeWithCoder:(NSCoder*)coder
{
  [coder encodeObject:self.stringProperty forKey:@"String Property"];
  [coder encodeObject:self.imageProperty forKey:@"Image Property"];
}

- (instancetype)initWithCoder:(NSCoder*)coder
{
  self = [super init]; // or `-initWithCoder:, if it is supported
  if (self)
  {
    self.stringProperty = [coder decodeObjectForKey:@"String Property"];
    self.imageProperty = [coder decodeObjectForKey:@"Image Property"];
  }
  return self;
}

如果您想将数据保存为属性列表文件,您只能使用属性列表classes。 NSString is a property list, but NSImage is not – 当然你的习惯 class 不是。因此,您必须将 NSImage 的实例和您的自定义 class 的实例转换为 NSData 的实例,因为 NSData 是一个 属性 列表。你可以用 - drum-roll - NSCoding 来做到这一点。只需使用键控存档器。 +archivedDataWithRootObject: (NSKeyedArchiver) 的结果是 NSData 的实例。回来的路你用NSKeyedUnarchiver.

但是,如果您不想使用通用的 属性 列表工具对其进行编辑,那么选择 属性 列表文件格式的理由并不多。

因此,直接回答您的问题:

is this a good idea? Am I missing something here?

没关系

can I save an array of objects with NSImage and String properties into a single file?

由于 NSArray 符合 NSCoding 并且是一个 属性 列表,因此两种方法都可以开箱即用。

I know I can save an image, fairly easily, but can I bundle them up into a single document?

您是文件的所有者并且您定义了文件格式。继续吧。

Is NSCoding the way to do this?

是的。

Do I need to convert the NSImage to NSData first?

仅当您要保存 属性 列表文件时。