5 Replies
      Latest reply on Feb 27, 2020 4:00 AM by lsamaria
      bitwit Level 1 Level 1 (0 points)

        I'm sucessfully saving and restoring world maps, however, if I place an anchor that is a subclass of ARAnchor it appears to either crash during saving, or failed to load due to "Invalid configuration."

        Just trying to determine if subclassing and archiving ARAnchor is intended to be possible. In the meantime I'll be looking for a work around.

        • Re: ARAnchor subclass causing issues when worldmap saved/restored
          bitwit Level 1 Level 1 (0 points)

          Just watched the SwiftShot WWDC video and realize they did exactly this (https://developer.apple.com/videos/play/wwdc2018/605 at 17mins). I'll have to investigate more on my side why this was happening, but I didn't have much trouble when  I switched back to using normal ARAnchors with unique identifiers as names.

            • Re: ARAnchor subclass causing issues when worldmap saved/restored
              Palace Software Level 1 Level 1 (0 points)

              Did you find a solution to this problem?

               

              I've just encountered the same issue, where a subclass of ARAnchor (even if it is an entirely empty subclass, differing from ARAnchor in name only) causes the secure NSKeyedArchiver to fail when trying to turn the ARWorldMap into archived Data.

               

              I've also discovered that turning my custom anchors back into vanilla ARAnchor objects allows the archiver to generate the archive successfully.

               

              It seems like a significant limitation to have all archived objects distinguished solely by a textual name, but I guess this avoids all sorts of potential problems with mapping between versions of (potentially incompatible) ARAnchor subclasses.

                • Re: ARAnchor subclass causing issues when worldmap saved/restored
                  Palace Software Level 1 Level 1 (0 points)

                  Here's a follow-up on this topic. It seems that subclasses of ARAnchor can be archived using the secure NSKeyedArchiver if they provide explicit (not implicit) conformance to NSSecureCoding.

                   

                  So something like the following won't work:

                   

                  class CustomARAnchor : ARAnchor {

                  }

                   

                  When you try to archive a ARWorldMap containing one or more CustomARAnchor objects (using NSKeyedArchiver.archivedData(withRootObject: worldMap, requiringSecureCoding: true)), the archiver throws a "Data is in the wrong format" error, and fails.

                   

                  But the following does work, and a WorldMap containing anchors as defined below are successfully archived:

                   

                  class CustomARAnchor : ARAnchor {

                   

                      required init(anchor: ARAnchor) {

                          super.init(anchor: anchor)

                      }

                   

                      override init(transform: simd_float4x4) {

                          super.init(transform: transform)

                      }

                   

                      override class var supportsSecureCoding: Bool {

                          return true

                      }

                   

                      required init?(coder aDecoder: NSCoder) {

                          super.init(coder: aDecoder)

                      }

                   

                      override func encode(with aCoder: NSCoder) {

                          super.encode(with: aCoder)

                      }

                   

                  }

                   

                  Note: Swift will always insists on the first constructor; my App was using the transform initializer for the subclass and Swift then required that the subclass also provide an override for this constructor.

                    • Re: ARAnchor subclass causing issues when worldmap saved/restored
                      Palace Software Level 1 Level 1 (0 points)

                      One final P.S. to this thread.

                       

                      Anyone subclassing ARAnchor needs also to be aware that ARKit clones these objects at 60Hz (every time an ARFrame is generated). When generating an ARWorldMap, it's these "clones" of your ARAnchor objects that you will receive in the ARWorldMap's .anchors list.

                       

                      For that reason, you need to ensure that your ARAnchor subclass conforms to the following rule (from https://developer.apple.com/documentation/arkit/aranchorcopying/3020708-init):

                       

                      /*

                           Each time ARKit generates a new ARFrame object (corresponding to an incoming frame of live camera video at 60 fps), ARKit calls this initializer to copy each of the anchors associated with the previous frame.

                          

                           Note: ARKit always calls this initializer with an anchor parameter of the same class as self.

                          

                           If you subclass ARAnchor to add extra properties, your implementation of this initializer should copy the values of those properties, then chain to the superclass initializer. For example, an AR game might define a BoardAnchor class to encode the position and size of a game board, so its version of this initializer would copy that size property:

                          

                           required init(anchor: ARAnchor) {

                              let other = anchor as! BoardAnchor

                              self.size = other.size

                              super.init(anchor: other)

                           }

                      */

                       

                      If your ARAnchor subclass contains optional properties, or properties with default values, it's easy to forget to clone these as well, in which case they are "lost" (reset to nil, or their explicit default values). If this happens, your ARAnchor subclasses won't be clones of the anchors you added to the ARSession at all, and you'll likely find this confusing when you try to reload and re-localize an ARSession using the archived ARWorldMap.