Непризнанный селектор, отправленный экземпляру при архивировании данных (NSCoding)

-(void)transformObjects:(NSMutableArray*)array key:(NSString*)key
{
    NSMutableArray* archiveArray = [[NSMutableArray alloc]initWithCapacity:array.count];

    for (Furniture *furniture in array) {

        // The error occurs on the line below
        NSData *furnitureEncodedObject = [NSKeyedArchiver archivedDataWithRootObject:furniture];
        [archiveArray addObject:furnitureEncodedObject];
    }

    NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
    [userData setObject:archiveArray forKey:key];
}

Журнал ошибок:

2014-03-04 10:55:27.881 AppName[10641:60b] -[Furniture encodeWithCoder:]: unrecognized selector sent to instance 0x15d43350

Я понятия не имею, почему я получаю "непризнанный селектор, отправленный экземпляру" при попытке архивирования объекта.

Ответы

Ответ 1

Вам необходимо внедрить протокол NSCoding внутри объекта "Мебель":

- (void)encodeWithCoder:(NSCoder *)aCoder{
  [aCoder encodeObject:self.yourpoperty forKey:@"PROPERTY_KEY"];
}

-(id)initWithCoder:(NSCoder *)aDecoder{
  if(self = [super init]){
    self.yourpoperty = [aDecoder decodeObjectForKey:@"PROPERTY_KEY"];
  }
  return self;
}

В основном вы указываете, что должно быть записано (закодировано) и считано из файла (декодировано). Обычно для каждого свойства, которое вы хотите сохранить в файле, вы делаете то же, что и здесь, в примере.

Ответ 2

Вам нужно реализовать NSCoding - вот пример с объектом с именем SNStock, который имеет два строковых свойства, ticker и name:

import Foundation

class SNStock: NSObject, NSCoding
{
  let ticker: NSString
  let name: NSString

  init(ticker: NSString, name: NSString)
  {
    self.ticker = ticker
    self.name = name
  }

  //MARK: NSCoding

  required init(coder aDecoder: NSCoder) {
    self.ticker = aDecoder.decodeObjectForKey("ticker") as! NSString
    self.name = aDecoder.decodeObjectForKey("name") as! NSString
  }

  func encodeWithCoder(aCoder: NSCoder) {
    aCoder.encodeObject(ticker, forKey: "ticker")
    aCoder.encodeObject(name, forKey: "name")
  }

  //MARK: NSObjectProtocol

  override func isEqual(object: AnyObject?) -> Bool {
    if let object = object as? SNStock {
      return self.ticker == object.ticker &&
        self.name == object.name
    } else {
      return false
    }
  }

  override var hash: Int {
    return ticker.hashValue
  }
}

Ответ 3

У вас есть пользовательский класс Furniture, который вы пытаетесь архивировать с помощью NSKeyedArchiver. Чтобы это сработало, класс Furniture должен соответствовать протоколу < NSCoding >. Это означает реализацию методов encodeWithCoder: и initWithCoder:.

В настоящее время вы не применяете эти методы. Вы должны добавить их.

Ответ 4

Я думаю, ваш класс мебели не реализует протокол NSCoding.