Не удается получить данные из NSUserDefaults в сегодняшнее расширение (Swift)

У меня есть группа массивов, каждая из которых содержит несколько экземпляров пользовательского объекта Task, который я создал. Я сохраняю массивы в NSUserDefaults следующим образом:

Пользовательский объект задачи

class Task:NSObject, NSCoding {
    var name:String
    var notes:String
    var date:NSDate
    var dateUse:Bool
    var taskCompleted:Bool

    init(name:String, notes:String, date:NSDate, dateUse:Bool, taskCompleted:Bool){
        self.name = name
        self.notes = notes
        self.date = date
        self.dateUse = dateUse
        self.taskCompleted = taskCompleted
    }

    required init(coder decoder: NSCoder){
        self.name = decoder.decodeObjectForKey("name") as! String
        self.notes = decoder.decodeObjectForKey("notes") as! String
        self.date = decoder.decodeObjectForKey("date") as! NSDate
        self.dateUse = decoder.decodeObjectForKey("dateUse") as! Bool
        self.taskCompleted = decoder.decodeObjectForKey("taskCompleted") as! Bool
    }

    func encodeWithCoder(coder: NSCoder) {
        coder.encodeObject(self.name, forKey: "name")
        coder.encodeObject(self.notes, forKey: "notes")
        coder.encodeObject(self.date, forKey: "date")
        coder.encodeObject(self.dateUse, forKey: "dateUse")
        coder.encodeObject(self.taskCompleted, forKey: "taskCompleted")
    }
}

Сохранение:

let defaults = NSUserDefaults(suiteName: "group.com.myGroupName")

let nowData = NSKeyedArchiver.archivedDataWithRootObject(nowTasks)
defaults!.setObject(nowData, forKey: "nowData")

Получение

let nowDataPull = defaults!.objectForKey("nowData") as? NSData
if let nowDataPull2 = nowDataPull{
   let nowTasks2 = NSKeyedUnarchiver.unarchiveObjectWithData(nowDataPull2) as? [Task]
   if let nowTasks21 = nowTasks2{
      nowTasks = nowTasks21
   }
}

Вышеупомянутый метод отлично работает для настройки и получения данных с самого iPhone. Однако этот метод не работает при попытке получить данные через расширение Today.

При попытке получить файл .swift с сегодняшним расширением я получаю следующие ошибки:

  • Не удалось наследовать разрешения CoreMedia от 52550: (ноль)

  • Завершение работы приложения из-за необработанного исключения «NSInvalidUnarchiveOperationException», причина: «* -[NSKeyedUnarchiver decodeObjectForKey:]: невозможно декодировать объект класса (MyAppName.Task) для ключа (NS.objects); класс может быть определен в исходном коде или в несвязанной библиотеке.


Я знаю, что расширение может читать данные, потому что когда я звоню:

if (defaults?.objectForKey("nowData") != nil){
   print("there is data")
}

Я получаю распечатанный ответ.


Я могу успешно сохранить целое число и получить его с помощью расширения Today, но не objectForKey


Я пробовал различные другие методы сохранения, включая файлы .plist, но ничего не работает. Продолжают появляться одни и те же ошибки. Любой вклад будет принят с благодарностью!


person Matt Butler    schedule 18.02.2016    source источник
comment
Я заметил, что ошибка относится к MyAppName.Task. Возможно, класс Task принадлежит другому модулю при компиляции в расширении Today?   -  person Mike Pollard    schedule 18.02.2016
comment
@MikePollard У меня есть полное объявление класса Task внутри файла с именем sharedCode.swift. Этот файл проверяется с помощью Target Membership как для основного приложения, так и для расширения Today.   -  person Matt Butler    schedule 19.02.2016


Ответы (3)


другой способ - исправить имя класса, используемого для NSCoding. Вам просто нужно использовать:

  • NSKeyedArchiver.setClassName("Task", forClass: Task.self перед сериализацией
  • NSKeyedUnarchiver.setClass(Task.self, forClassName: "Task") перед десериализацией

везде, где нужно.

Похоже, в расширениях iOS перед именем класса стоит название расширения.

person teriiehina    schedule 11.05.2016
comment
Это наиболее общее решение для расширений iOS (и должно быть принятым ответом). - person Ryan H.; 23.10.2016

Установить объект

let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject("iOS", forKey: "userNameKey")

defaults.setInteger(25, forKey: "Age")
defaults.setBool(true, forKey: "UseTouchID")
defaults.setDouble(M_PI, forKey: "Pi")

Чтение

let defaults = NSUserDefaults.standardUserDefaults()
let name = defaults.stringForKey("userNameKey")
person Waruna    schedule 18.02.2016
comment
Я не думаю, что standardUserDefaults() работает с обменом данными между приложением и расширением, не так ли? Я почти уверен, что вы должны объявить имя группы. - person Matt Butler; 19.02.2016

Временное решение:

Итак, я нашел обходной путь (который на самом деле более эффективен) для моей проблемы. Поскольку декодирование [Task] вызывало проблемы, я решил пойти дальше и извлечь данные из массива, внутри которого не было объектов, а были только NSDate() экземпляры. Благодаря этому теперь я могу сохранять и получать доступ к важным аспектам данных, которые нужны сегодняшнему расширению. Я призываю всех, у кого есть проблемы с декодированием пользовательского класса, попытаться упростить ваши данные, если это вообще возможно, чтобы получить и использовать их в вашем расширении. Я не совсем уверен, в чем проблема была или есть, но получение простых данных из массива, хранящегося в NSUserDefaults, работает без проблем.

Надеюсь, что вся эта ерунда может помочь кому-то еще!

person Matt Butler    schedule 20.02.2016
comment
Я тоже склоняюсь к тому же. В моем случае я знаю, что пользовательский класс связан как с приложением, так и с расширением «Сегодня», но архивирование и разархивирование работает только в самом приложении для iPhone. Я не могу не чувствовать, что должен быть лучший способ сделать это!! - person cptdanko; 16.03.2016
comment
У меня была точно такая же проблема. После нескольких дней попыток я в конце концов нашел другое решение. Вы также можете подумать об этом. - person Matt Butler; 16.03.2016