Unarchive Array with NSKeyedUnarchiver unarchivedObject(ofClass:from:)










5















Since upgrading to Swift 4.2 I've found that many of the NSKeyedUnarchiver and NSKeyedArchiver methods have been deprecated and we must now use the type method static func unarchivedObject<DecodedObjectType>(ofClass: DecodedObjectType.Type, from: Data) -> DecodedObjectType? to unarchive data.



I have managed to successfully archive an Array of my bespoke class WidgetData, which is an NSObject subclass:



private static func archiveWidgetDataArray(widgetDataArray : [WidgetData]) -> NSData 

guard let data = try? NSKeyedArchiver.archivedData(withRootObject: widgetDataArray as Array, requiringSecureCoding: false) as NSData
else fatalError("Can't encode data")

return data




The problem comes when I try to unarchive this data:



static func loadWidgetDataArray() -> [WidgetData]? 

if isKeyPresentInUserDefaults(key: USER_DEFAULTS_KEY_WIDGET_DATA)

if let unarchivedObject = UserDefaults.standard.object(forKey: USER_DEFAULTS_KEY_WIDGET_DATA) as? Data

//THIS FUNCTION HAS NOW BEEN DEPRECATED:
//return NSKeyedUnarchiver.unarchiveObject(with: unarchivedObject as Data) as? [WidgetData]

guard let nsArray = try? NSKeyedUnarchiver.unarchivedObject(ofClass: NSArray.self, from: unarchivedObject as Data) else
fatalError("loadWidgetDataArray - Can't encode data")


guard let array = nsArray as? Array<WidgetData> else
fatalError("loadWidgetDataArray - Can't get Array")


return array





return nil




But this fails, as using Array.self instead of NSArray.self is disallowed. What am I doing wrong and how can I fix this to unarchive my Array?










share|improve this question
























  • Check this for a more swifty solution stackoverflow.com/a/51460950/5820010

    – Sh_Khan
    Jul 23 '18 at 21:53











  • What "fails"? What output do you get? You aren't using Array.self anywhere.

    – Paulw11
    Jul 23 '18 at 22:34











  • When changed to Array.self instead of NSArray.self, the pre-compiler complains: Incorrect argument label in call (have 'ofClass:from:', expected 'ofClasses:from:') Replace 'ofClass' with 'ofClasses'. Which implies Array.self can't be used. When I use NSArray.self it compiles without issue & runs. But gets caught by the fatal error as the resulting 'nsArray' is nil.

    – Geoff H
    Jul 23 '18 at 22:38












  • So, what happens when you use NSKeyedUnarchiver.unarchivedObject(ofClasses: [Array<WidgetData>.self], from: unarchivedObject as Data)? Also, instead of using try? use do/try/catch so that you can print the actual error that occurred.

    – Paulw11
    Jul 23 '18 at 22:45












  • It results in the following complaint: Cannot convert value of type 'Array<WidgetData>.Type' to expected element type 'AnyObject.Type' Insert ' as! AnyObject.Type'

    – Geoff H
    Jul 23 '18 at 22:59















5















Since upgrading to Swift 4.2 I've found that many of the NSKeyedUnarchiver and NSKeyedArchiver methods have been deprecated and we must now use the type method static func unarchivedObject<DecodedObjectType>(ofClass: DecodedObjectType.Type, from: Data) -> DecodedObjectType? to unarchive data.



I have managed to successfully archive an Array of my bespoke class WidgetData, which is an NSObject subclass:



private static func archiveWidgetDataArray(widgetDataArray : [WidgetData]) -> NSData 

guard let data = try? NSKeyedArchiver.archivedData(withRootObject: widgetDataArray as Array, requiringSecureCoding: false) as NSData
else fatalError("Can't encode data")

return data




The problem comes when I try to unarchive this data:



static func loadWidgetDataArray() -> [WidgetData]? 

if isKeyPresentInUserDefaults(key: USER_DEFAULTS_KEY_WIDGET_DATA)

if let unarchivedObject = UserDefaults.standard.object(forKey: USER_DEFAULTS_KEY_WIDGET_DATA) as? Data

//THIS FUNCTION HAS NOW BEEN DEPRECATED:
//return NSKeyedUnarchiver.unarchiveObject(with: unarchivedObject as Data) as? [WidgetData]

guard let nsArray = try? NSKeyedUnarchiver.unarchivedObject(ofClass: NSArray.self, from: unarchivedObject as Data) else
fatalError("loadWidgetDataArray - Can't encode data")


guard let array = nsArray as? Array<WidgetData> else
fatalError("loadWidgetDataArray - Can't get Array")


return array





return nil




But this fails, as using Array.self instead of NSArray.self is disallowed. What am I doing wrong and how can I fix this to unarchive my Array?










share|improve this question
























  • Check this for a more swifty solution stackoverflow.com/a/51460950/5820010

    – Sh_Khan
    Jul 23 '18 at 21:53











  • What "fails"? What output do you get? You aren't using Array.self anywhere.

    – Paulw11
    Jul 23 '18 at 22:34











  • When changed to Array.self instead of NSArray.self, the pre-compiler complains: Incorrect argument label in call (have 'ofClass:from:', expected 'ofClasses:from:') Replace 'ofClass' with 'ofClasses'. Which implies Array.self can't be used. When I use NSArray.self it compiles without issue & runs. But gets caught by the fatal error as the resulting 'nsArray' is nil.

    – Geoff H
    Jul 23 '18 at 22:38












  • So, what happens when you use NSKeyedUnarchiver.unarchivedObject(ofClasses: [Array<WidgetData>.self], from: unarchivedObject as Data)? Also, instead of using try? use do/try/catch so that you can print the actual error that occurred.

    – Paulw11
    Jul 23 '18 at 22:45












  • It results in the following complaint: Cannot convert value of type 'Array<WidgetData>.Type' to expected element type 'AnyObject.Type' Insert ' as! AnyObject.Type'

    – Geoff H
    Jul 23 '18 at 22:59













5












5








5


2






Since upgrading to Swift 4.2 I've found that many of the NSKeyedUnarchiver and NSKeyedArchiver methods have been deprecated and we must now use the type method static func unarchivedObject<DecodedObjectType>(ofClass: DecodedObjectType.Type, from: Data) -> DecodedObjectType? to unarchive data.



I have managed to successfully archive an Array of my bespoke class WidgetData, which is an NSObject subclass:



private static func archiveWidgetDataArray(widgetDataArray : [WidgetData]) -> NSData 

guard let data = try? NSKeyedArchiver.archivedData(withRootObject: widgetDataArray as Array, requiringSecureCoding: false) as NSData
else fatalError("Can't encode data")

return data




The problem comes when I try to unarchive this data:



static func loadWidgetDataArray() -> [WidgetData]? 

if isKeyPresentInUserDefaults(key: USER_DEFAULTS_KEY_WIDGET_DATA)

if let unarchivedObject = UserDefaults.standard.object(forKey: USER_DEFAULTS_KEY_WIDGET_DATA) as? Data

//THIS FUNCTION HAS NOW BEEN DEPRECATED:
//return NSKeyedUnarchiver.unarchiveObject(with: unarchivedObject as Data) as? [WidgetData]

guard let nsArray = try? NSKeyedUnarchiver.unarchivedObject(ofClass: NSArray.self, from: unarchivedObject as Data) else
fatalError("loadWidgetDataArray - Can't encode data")


guard let array = nsArray as? Array<WidgetData> else
fatalError("loadWidgetDataArray - Can't get Array")


return array





return nil




But this fails, as using Array.self instead of NSArray.self is disallowed. What am I doing wrong and how can I fix this to unarchive my Array?










share|improve this question
















Since upgrading to Swift 4.2 I've found that many of the NSKeyedUnarchiver and NSKeyedArchiver methods have been deprecated and we must now use the type method static func unarchivedObject<DecodedObjectType>(ofClass: DecodedObjectType.Type, from: Data) -> DecodedObjectType? to unarchive data.



I have managed to successfully archive an Array of my bespoke class WidgetData, which is an NSObject subclass:



private static func archiveWidgetDataArray(widgetDataArray : [WidgetData]) -> NSData 

guard let data = try? NSKeyedArchiver.archivedData(withRootObject: widgetDataArray as Array, requiringSecureCoding: false) as NSData
else fatalError("Can't encode data")

return data




The problem comes when I try to unarchive this data:



static func loadWidgetDataArray() -> [WidgetData]? 

if isKeyPresentInUserDefaults(key: USER_DEFAULTS_KEY_WIDGET_DATA)

if let unarchivedObject = UserDefaults.standard.object(forKey: USER_DEFAULTS_KEY_WIDGET_DATA) as? Data

//THIS FUNCTION HAS NOW BEEN DEPRECATED:
//return NSKeyedUnarchiver.unarchiveObject(with: unarchivedObject as Data) as? [WidgetData]

guard let nsArray = try? NSKeyedUnarchiver.unarchivedObject(ofClass: NSArray.self, from: unarchivedObject as Data) else
fatalError("loadWidgetDataArray - Can't encode data")


guard let array = nsArray as? Array<WidgetData> else
fatalError("loadWidgetDataArray - Can't get Array")


return array





return nil




But this fails, as using Array.self instead of NSArray.self is disallowed. What am I doing wrong and how can I fix this to unarchive my Array?







ios swift nskeyedunarchiver ios12






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Aug 1 '18 at 20:06









Ashley Mills

29k989117




29k989117










asked Jul 23 '18 at 21:47









Geoff HGeoff H

1,2611630




1,2611630












  • Check this for a more swifty solution stackoverflow.com/a/51460950/5820010

    – Sh_Khan
    Jul 23 '18 at 21:53











  • What "fails"? What output do you get? You aren't using Array.self anywhere.

    – Paulw11
    Jul 23 '18 at 22:34











  • When changed to Array.self instead of NSArray.self, the pre-compiler complains: Incorrect argument label in call (have 'ofClass:from:', expected 'ofClasses:from:') Replace 'ofClass' with 'ofClasses'. Which implies Array.self can't be used. When I use NSArray.self it compiles without issue & runs. But gets caught by the fatal error as the resulting 'nsArray' is nil.

    – Geoff H
    Jul 23 '18 at 22:38












  • So, what happens when you use NSKeyedUnarchiver.unarchivedObject(ofClasses: [Array<WidgetData>.self], from: unarchivedObject as Data)? Also, instead of using try? use do/try/catch so that you can print the actual error that occurred.

    – Paulw11
    Jul 23 '18 at 22:45












  • It results in the following complaint: Cannot convert value of type 'Array<WidgetData>.Type' to expected element type 'AnyObject.Type' Insert ' as! AnyObject.Type'

    – Geoff H
    Jul 23 '18 at 22:59

















  • Check this for a more swifty solution stackoverflow.com/a/51460950/5820010

    – Sh_Khan
    Jul 23 '18 at 21:53











  • What "fails"? What output do you get? You aren't using Array.self anywhere.

    – Paulw11
    Jul 23 '18 at 22:34











  • When changed to Array.self instead of NSArray.self, the pre-compiler complains: Incorrect argument label in call (have 'ofClass:from:', expected 'ofClasses:from:') Replace 'ofClass' with 'ofClasses'. Which implies Array.self can't be used. When I use NSArray.self it compiles without issue & runs. But gets caught by the fatal error as the resulting 'nsArray' is nil.

    – Geoff H
    Jul 23 '18 at 22:38












  • So, what happens when you use NSKeyedUnarchiver.unarchivedObject(ofClasses: [Array<WidgetData>.self], from: unarchivedObject as Data)? Also, instead of using try? use do/try/catch so that you can print the actual error that occurred.

    – Paulw11
    Jul 23 '18 at 22:45












  • It results in the following complaint: Cannot convert value of type 'Array<WidgetData>.Type' to expected element type 'AnyObject.Type' Insert ' as! AnyObject.Type'

    – Geoff H
    Jul 23 '18 at 22:59
















Check this for a more swifty solution stackoverflow.com/a/51460950/5820010

– Sh_Khan
Jul 23 '18 at 21:53





Check this for a more swifty solution stackoverflow.com/a/51460950/5820010

– Sh_Khan
Jul 23 '18 at 21:53













What "fails"? What output do you get? You aren't using Array.self anywhere.

– Paulw11
Jul 23 '18 at 22:34





What "fails"? What output do you get? You aren't using Array.self anywhere.

– Paulw11
Jul 23 '18 at 22:34













When changed to Array.self instead of NSArray.self, the pre-compiler complains: Incorrect argument label in call (have 'ofClass:from:', expected 'ofClasses:from:') Replace 'ofClass' with 'ofClasses'. Which implies Array.self can't be used. When I use NSArray.self it compiles without issue & runs. But gets caught by the fatal error as the resulting 'nsArray' is nil.

– Geoff H
Jul 23 '18 at 22:38






When changed to Array.self instead of NSArray.self, the pre-compiler complains: Incorrect argument label in call (have 'ofClass:from:', expected 'ofClasses:from:') Replace 'ofClass' with 'ofClasses'. Which implies Array.self can't be used. When I use NSArray.self it compiles without issue & runs. But gets caught by the fatal error as the resulting 'nsArray' is nil.

– Geoff H
Jul 23 '18 at 22:38














So, what happens when you use NSKeyedUnarchiver.unarchivedObject(ofClasses: [Array<WidgetData>.self], from: unarchivedObject as Data)? Also, instead of using try? use do/try/catch so that you can print the actual error that occurred.

– Paulw11
Jul 23 '18 at 22:45






So, what happens when you use NSKeyedUnarchiver.unarchivedObject(ofClasses: [Array<WidgetData>.self], from: unarchivedObject as Data)? Also, instead of using try? use do/try/catch so that you can print the actual error that occurred.

– Paulw11
Jul 23 '18 at 22:45














It results in the following complaint: Cannot convert value of type 'Array<WidgetData>.Type' to expected element type 'AnyObject.Type' Insert ' as! AnyObject.Type'

– Geoff H
Jul 23 '18 at 22:59





It results in the following complaint: Cannot convert value of type 'Array<WidgetData>.Type' to expected element type 'AnyObject.Type' Insert ' as! AnyObject.Type'

– Geoff H
Jul 23 '18 at 22:59












4 Answers
4






active

oldest

votes


















6














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.






share|improve this answer























  • That hit the nail on the head. Thank you so much. Yes, I'm making a new app. If you could shed a little light on Codable.. You got my attention. Where should I start with it & why is it important.

    – Geoff H
    Jul 23 '18 at 23:03






  • 2





    @GeoffH, it's native Swift way of serializing (archiving). (For example, it works with [WidgetData].self, you have no need to care about NSArray or some other NS-things.) Better start with searching "swift codable" and you can find many good articles.

    – OOPer
    Jul 23 '18 at 23:08











  • Will do. Thank you so much for your help.

    – Geoff H
    Jul 23 '18 at 23:10


















3














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.





share|improve this answer






























    2














     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






    share|improve this answer






























      1














      You are likely looking for this:



      if let widgetsData = UserDefaults.standard.data(forKey: USER_DEFAULTS_KEY_WIDGET_DATA) 
      if let widgets = (try? NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSArray.self, WidgetData.self], from: widgetsData)) as? [WidgetData]
      // your code







      share|improve this answer























      • I could resolve a same problem with your approach using ‘[NSArray.self, WidgetData.self]’. However I cound not find a public document about your approach. Do you know document url?

        – Mao Nishi
        Dec 6 '18 at 8:29










      Your Answer






      StackExchange.ifUsing("editor", function ()
      StackExchange.using("externalEditor", function ()
      StackExchange.using("snippets", function ()
      StackExchange.snippets.init();
      );
      );
      , "code-snippets");

      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "1"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader:
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      ,
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );













      draft saved

      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f51487622%2funarchive-array-with-nskeyedunarchiver-unarchivedobjectofclassfrom%23new-answer', 'question_page');

      );

      Post as a guest















      Required, but never shown

























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      6














      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.






      share|improve this answer























      • That hit the nail on the head. Thank you so much. Yes, I'm making a new app. If you could shed a little light on Codable.. You got my attention. Where should I start with it & why is it important.

        – Geoff H
        Jul 23 '18 at 23:03






      • 2





        @GeoffH, it's native Swift way of serializing (archiving). (For example, it works with [WidgetData].self, you have no need to care about NSArray or some other NS-things.) Better start with searching "swift codable" and you can find many good articles.

        – OOPer
        Jul 23 '18 at 23:08











      • Will do. Thank you so much for your help.

        – Geoff H
        Jul 23 '18 at 23:10















      6














      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.






      share|improve this answer























      • That hit the nail on the head. Thank you so much. Yes, I'm making a new app. If you could shed a little light on Codable.. You got my attention. Where should I start with it & why is it important.

        – Geoff H
        Jul 23 '18 at 23:03






      • 2





        @GeoffH, it's native Swift way of serializing (archiving). (For example, it works with [WidgetData].self, you have no need to care about NSArray or some other NS-things.) Better start with searching "swift codable" and you can find many good articles.

        – OOPer
        Jul 23 '18 at 23:08











      • Will do. Thank you so much for your help.

        – Geoff H
        Jul 23 '18 at 23:10













      6












      6








      6







      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.






      share|improve this answer













      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.







      share|improve this answer












      share|improve this answer



      share|improve this answer










      answered Jul 23 '18 at 22:40









      OOPerOOPer

      35.2k46487




      35.2k46487












      • That hit the nail on the head. Thank you so much. Yes, I'm making a new app. If you could shed a little light on Codable.. You got my attention. Where should I start with it & why is it important.

        – Geoff H
        Jul 23 '18 at 23:03






      • 2





        @GeoffH, it's native Swift way of serializing (archiving). (For example, it works with [WidgetData].self, you have no need to care about NSArray or some other NS-things.) Better start with searching "swift codable" and you can find many good articles.

        – OOPer
        Jul 23 '18 at 23:08











      • Will do. Thank you so much for your help.

        – Geoff H
        Jul 23 '18 at 23:10

















      • That hit the nail on the head. Thank you so much. Yes, I'm making a new app. If you could shed a little light on Codable.. You got my attention. Where should I start with it & why is it important.

        – Geoff H
        Jul 23 '18 at 23:03






      • 2





        @GeoffH, it's native Swift way of serializing (archiving). (For example, it works with [WidgetData].self, you have no need to care about NSArray or some other NS-things.) Better start with searching "swift codable" and you can find many good articles.

        – OOPer
        Jul 23 '18 at 23:08











      • Will do. Thank you so much for your help.

        – Geoff H
        Jul 23 '18 at 23:10
















      That hit the nail on the head. Thank you so much. Yes, I'm making a new app. If you could shed a little light on Codable.. You got my attention. Where should I start with it & why is it important.

      – Geoff H
      Jul 23 '18 at 23:03





      That hit the nail on the head. Thank you so much. Yes, I'm making a new app. If you could shed a little light on Codable.. You got my attention. Where should I start with it & why is it important.

      – Geoff H
      Jul 23 '18 at 23:03




      2




      2





      @GeoffH, it's native Swift way of serializing (archiving). (For example, it works with [WidgetData].self, you have no need to care about NSArray or some other NS-things.) Better start with searching "swift codable" and you can find many good articles.

      – OOPer
      Jul 23 '18 at 23:08





      @GeoffH, it's native Swift way of serializing (archiving). (For example, it works with [WidgetData].self, you have no need to care about NSArray or some other NS-things.) Better start with searching "swift codable" and you can find many good articles.

      – OOPer
      Jul 23 '18 at 23:08













      Will do. Thank you so much for your help.

      – Geoff H
      Jul 23 '18 at 23:10





      Will do. Thank you so much for your help.

      – Geoff H
      Jul 23 '18 at 23:10













      3














      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.





      share|improve this answer



























        3














        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.





        share|improve this answer

























          3












          3








          3







          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.





          share|improve this answer













          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.






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Sep 20 '18 at 22:34









          Maciej SMaciej S

          121110




          121110





















              2














               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






              share|improve this answer



























                2














                 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






                share|improve this answer

























                  2












                  2








                  2







                   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






                  share|improve this answer













                   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







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Oct 23 '18 at 9:35









                  user1828845user1828845

                  9019




                  9019





















                      1














                      You are likely looking for this:



                      if let widgetsData = UserDefaults.standard.data(forKey: USER_DEFAULTS_KEY_WIDGET_DATA) 
                      if let widgets = (try? NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSArray.self, WidgetData.self], from: widgetsData)) as? [WidgetData]
                      // your code







                      share|improve this answer























                      • I could resolve a same problem with your approach using ‘[NSArray.self, WidgetData.self]’. However I cound not find a public document about your approach. Do you know document url?

                        – Mao Nishi
                        Dec 6 '18 at 8:29















                      1














                      You are likely looking for this:



                      if let widgetsData = UserDefaults.standard.data(forKey: USER_DEFAULTS_KEY_WIDGET_DATA) 
                      if let widgets = (try? NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSArray.self, WidgetData.self], from: widgetsData)) as? [WidgetData]
                      // your code







                      share|improve this answer























                      • I could resolve a same problem with your approach using ‘[NSArray.self, WidgetData.self]’. However I cound not find a public document about your approach. Do you know document url?

                        – Mao Nishi
                        Dec 6 '18 at 8:29













                      1












                      1








                      1







                      You are likely looking for this:



                      if let widgetsData = UserDefaults.standard.data(forKey: USER_DEFAULTS_KEY_WIDGET_DATA) 
                      if let widgets = (try? NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSArray.self, WidgetData.self], from: widgetsData)) as? [WidgetData]
                      // your code







                      share|improve this answer













                      You are likely looking for this:



                      if let widgetsData = UserDefaults.standard.data(forKey: USER_DEFAULTS_KEY_WIDGET_DATA) 
                      if let widgets = (try? NSKeyedUnarchiver.unarchivedObject(ofClasses: [NSArray.self, WidgetData.self], from: widgetsData)) as? [WidgetData]
                      // your code








                      share|improve this answer












                      share|improve this answer



                      share|improve this answer










                      answered Oct 11 '18 at 11:26









                      HopreeeenjustHopreeeenjust

                      10714




                      10714












                      • I could resolve a same problem with your approach using ‘[NSArray.self, WidgetData.self]’. However I cound not find a public document about your approach. Do you know document url?

                        – Mao Nishi
                        Dec 6 '18 at 8:29

















                      • I could resolve a same problem with your approach using ‘[NSArray.self, WidgetData.self]’. However I cound not find a public document about your approach. Do you know document url?

                        – Mao Nishi
                        Dec 6 '18 at 8:29
















                      I could resolve a same problem with your approach using ‘[NSArray.self, WidgetData.self]’. However I cound not find a public document about your approach. Do you know document url?

                      – Mao Nishi
                      Dec 6 '18 at 8:29





                      I could resolve a same problem with your approach using ‘[NSArray.self, WidgetData.self]’. However I cound not find a public document about your approach. Do you know document url?

                      – Mao Nishi
                      Dec 6 '18 at 8:29

















                      draft saved

                      draft discarded
















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid


                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.

                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f51487622%2funarchive-array-with-nskeyedunarchiver-unarchivedobjectofclassfrom%23new-answer', 'question_page');

                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      這個網誌中的熱門文章

                      What does pagestruct do in Eviews?

                      Dutch intervention in Lombok and Karangasem

                      Channel Islands