Search code examples
arraysswiftpersistencegoogle-maps-sdk-iospolyline

How to save a [GMSPolyline] so that when the user closes and opens the app it still retains the data


Hello in my current project I have:

class SecondController: UIViewController, CLLocationManagerDelegate {

var allPoly : [GMSPolyline] = []
private let rootKey = "rootKey"

func applicationWillResignActive(notification: NSNotification)
    {
        let filePath = self.dataFilePath()
        let savedPolys = SavedPolys()
        let array = self.allPoly as NSArray
        savedPolys.alPoly = array as? [GMSPolyline]
        let data = NSMutableData()
        let archiver = NSKeyedArchiver(forWritingWith: data)
        archiver.encode(savedPolys, forKey: rootKey)
        archiver.finishEncoding()
        data.write(toFile: filePath, atomically: true)
    }

    func dataFilePath() -> String
    {
        let paths = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
        let documentsDirectory = paths[0] as NSString
        return documentsDirectory.appendingPathComponent("data.archive") as String
    }

    func buttonPressed()
   {
      //adds a polyline to allPoly!
   }

   }

As well as another class:

import Foundation
import GoogleMaps

class SavedPolys: NSObject, NSCoding, NSCopying
{
    var alPoly: [GMSPolyline]?
    let polyKey = "polyKey"

    override init()
    {

    }

    required init?(coder aDecoder: NSCoder)
    {
        alPoly = aDecoder.decodeObject(forKey: polyKey) as? [GMSPolyline]
    }

    func encode(with aCoder: NSCoder) {
        if let savePoly = alPoly
        {
            aCoder.encode(savePoly, forKey: polyKey)
        }
    }

    func copy(with zone: NSZone? = nil) -> Any {
        let copy = SavedPolys()
        if let polysToCopy = alPoly
        {
            var newPolys = Array<GMSPolyline>()
            for poly in polysToCopy
            {
                newPolys.append(poly)
            }
            copy.alPoly = newPolys
        }
        return copy
    }
}

I am trying to make it so if the user adds polys to the allPoly array, and then closes their app, the array will be saved and then reloaded when they open the application. I have tried following a chapter out of my Class' textbook (which is where all of this is coming from), but this current code gives me an error on this line: "archiver.encode(savedPolys, forKey: rootKey)". It says "unrecognized selector sent to instance". Can anyone help me? Is there a simpler way? Thanks!


Solution

  • The code you are copying is a bit old and there have been changes to the API that is why it is throwing errors. Here are the modified code:

    Swift 2.3

    class SavedPolys : NSObject, NSCoding, NSCopying
    {
      var alPoly: [GMSPolyline]?
      let polyKey = "polyKey"
    
      override init()
      {
    
      }
    
      required init?(coder aDecoder: NSCoder)
      {
        alPoly = aDecoder.decodeObjectForKey(polyKey) as? [GMSPolyline]
      }
    
      func encodeWithCoder(aCoder: NSCoder)
      {
        if let savePoly = alPoly
        {
          aCoder.encodeObject(savePoly, forKey: polyKey)
        }
      }
    
      func copyWithZone(zone: NSZone) -> AnyObject
      {
        let copy = SavedPolys()
        if let polysToCopy = alPoly
        {
          var newPolys = Array<GMSPolyline>()
          for poly in polysToCopy
          {
            newPolys.append(poly)
          }
          copy.alPoly = newPolys
        }
        return copy
      }
    }
    
    
    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
    
      var window: UIWindow?
    
      var allPoly : [GMSPolyline] = []
      private let rootKey = "rootKey"
    
      func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        // Override point for customization after application launch.
    
        let filePath = self.dataFilePath()
        let savedPolys = SavedPolys()
        let array = self.allPoly as NSArray
        savedPolys.alPoly = array as? [GMSPolyline]
        let data = NSMutableData()
        let archiver = NSKeyedArchiver(forWritingWithMutableData: data)
        archiver.encodeObject(savedPolys, forKey: rootKey)
        archiver.finishEncoding()
        data.writeToURL(NSURL(fileURLWithPath: filePath), atomically: true)
    
    
        return true
      }
    
      func dataFilePath() -> String
      {
        let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
        let documentsDirectory = paths[0] as NSString
        return documentsDirectory.stringByAppendingPathComponent("data.archive")
      }
    }
    

    Swift 3.0

    class SavedPolys : NSObject, NSCoding, NSCopying
    {
      var alPoly: [GMSPolyline]?
      let polyKey = "polyKey"
    
      override init()
      {
    
      }
    
      required init?(coder aDecoder: NSCoder)
      {
        alPoly = aDecoder.decodeObject(forKey: polyKey) as? [GMSPolyline]
      }
    
      func encode(with aCoder: NSCoder)
      {
        if let savePoly = alPoly
        {
          aCoder.encode(savePoly, forKey: polyKey)
        }
      }
    
      func copy(with zone: NSZone? = nil) -> Any
      {
        let copy = SavedPolys()
        if let polysToCopy = alPoly
        {
          var newPolys = Array<GMSPolyline>()
          for poly in polysToCopy
          {
            newPolys.append(poly)
          }
          copy.alPoly = newPolys
        }
        return copy
      }
    }
    
    @UIApplicationMain
    class AppDelegate: UIResponder, UIApplicationDelegate {
    
      var window: UIWindow?
      var allPoly : [GMSPolyline] = []
      private let rootKey = "rootKey"
    
      func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        let filePath = self.dataFilePath()
        let savedPolys = SavedPolys()
        let array = self.allPoly as NSArray
        savedPolys.alPoly = array as? [GMSPolyline]
        let data = NSMutableData()
        let archiver = NSKeyedArchiver(forWritingWith: data)
        archiver.encode(savedPolys, forKey: rootKey)
        archiver.finishEncoding()
        data.write(to: NSURL(fileURLWithPath: filePath) as URL, atomically: true)
    
        return true
      }
    
      func dataFilePath() -> String
      {
        let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
        let documentsDirectory = paths[0] as NSString
        return documentsDirectory.appendingPathComponent("data.archive")
      }
    }