Unarchive Array with NSKeyedUnarchiver unarchivedObject(ofClass:from:)

You can use unarchiveTopLevelObjectWithData(_:) to unarchive the data archived by archivedData(withRootObject:requiringSecureCoding:). (I believe this is not deprecated yet.)

But before showing some code, you should better:

  • Avoid using NSData, use Data instead

  • Avoid using try? which disposes error info useful for debugging

  • Remove all unneeded casts


Try this:

private static func archiveWidgetDataArray(widgetDataArray : [WidgetData]) -> Data {
    do {
        let data = try NSKeyedArchiver.archivedData(withRootObject: widgetDataArray, requiringSecureCoding: false)

        return data
    } catch {
        fatalError("Can't encode data: \(error)")
    }

}

static func loadWidgetDataArray() -> [WidgetData]? {
    guard
        isKeyPresentInUserDefaults(key: USER_DEFAULTS_KEY_WIDGET_DATA), //<- Do you really need this line?
        let unarchivedObject = UserDefaults.standard.data(forKey: USER_DEFAULTS_KEY_WIDGET_DATA)
    else {
        return nil
    }
    do {
        guard let array = try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(unarchivedObject) as? [WidgetData] else {
            fatalError("loadWidgetDataArray - Can't get Array")
        }
        return array
    } catch {
        fatalError("loadWidgetDataArray - Can't encode data: \(error)")
    }
}

But if you are making a new app, you should better consider using Codable.


unarchiveTopLevelObjectWithData(_:) 

is deprecated as well. So to unarchive data without secure coding you need to:

  1. Create NSKeyedUnarchiver with init(forReadingFrom: Data)
  2. Set requiresSecureCoding of created unarchiver to false.
  3. Call decodeObject(of: [AnyClass]?, forKey: String) -> Any? to get your object, just use proper class and NSKeyedArchiveRootObjectKeyas key.

 if #available(iOS 12.0, *) {
        guard let unarchivedFavorites = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(favoritesData!)
            else {
                return
        }
        self.channelFavorites = unarchivedFavorites as! [ChannelFavorite]
    } else {
        if let unarchivedFavorites = NSKeyedUnarchiver.unarchiveObject(with: favoritesData!) as? [ChannelFavorite] {
            self.channelFavorites = unarchivedFavorites
        }

// Achieving data

 if #available(iOS 12.0, *) {
            // use iOS 12-only feature
            do {
                let data = try NSKeyedArchiver.archivedData(withRootObject: channelFavorites, requiringSecureCoding: false)
                UserDefaults.standard.set(data, forKey: "channelFavorites")
            } catch {
                return
            }
        } else {
            // handle older versions
            let data = NSKeyedArchiver.archivedData(withRootObject: channelFavorites)
            UserDefaults.standard.set(data, forKey: "channelFavorites")
        }

This is the way I have updated my code and its working for me