Pixxl
Pixxl

Reputation: 996

How to serialize data like a buffer object in Objective-C for NativeScript to consume

While working to add cross-platform support to a NativeScript plugin, there are areas of the plugin that will need to preserve an Object state. This means that at a given time, the state of the data needs to be preserved and stored within NativeScript (TypesScript/JavaScript) and reinstated without data corruption.

While this seems to be a feat pretty straightforward in many JAVA libraries used for the Android side of the plugin, I am unsure how to replicate this for iOS development.

Upvotes: 0

Views: 247

Answers (1)

Pixxl
Pixxl

Reputation: 996

Researching this topic online can lead to various answers, most of which seem to require the developer to create specific methods on a given Object/Class in order to support serialization.

Option 1 - NSCoding Protocol

The NSCoding protocol — Source (Apple) — declares the two methods that a class must implement so that instances of that class can be encoded and decoded. This capability provides the basis for archiving (where objects and other structures are stored on disk) and distribution (where objects are copied to different address spaces).

The two methods mentioned are:

- (void) encodeWithCoder:(NSCoder*)encoder;
- (id) initWithCoder:(NSCoder*)decoder;

While this could work in most circumstances, this would require the NativeScript developer to figure out a way to create yet another wrapper for an iOS library (likely to be a pod package). This is more hands on than needs to be and may not be available in most situations.

Option 2 - NSKeyedArchiver/NSKeyedUnarchiver

The NSKeyedArchiver and companion NSKeyedUnarchiver protocols provide a way to encode/decode objects (and scalar values) into an architecture-independent suitable for storage in a file.

This option seems less intrusive and allows for the archived object to be turned into something sharable between environments such as base64:

declare var NSDataBase64EncodingEndLineWithLineFeed;
declare var NSDataBase64DecodingIgnoreUnknownCharacters;

// archive class instance as base64 string
const archivedObject = NSKeyedArchiver.archivedDataWithRootObject(someClassInstance);
const base64Archive = archivedObject.base64EncodedStringWithOptions(NSDataBase64EncodingEndLineWithLineFeed);

// unarchive back into a class instance
const rawData = NSData.alloc().initWithBase64EncodedStringOptions(base64Archive, NSDataBase64DecodingIgnoreUnknownCharacters);
const newClassInstance = NSKeyedUnarchiver.unarchivedObjectOfClassFromDataError(NSObject, rawData);

I was able to learn both of these concepts from an old article lost in time (but thankfully saved due to the WayBackMachine) — CocoaHeads - NSCoding

In addition to the information above, I believe one could also use NativeScript to extend an existing ObjC Class and add the required encodeWithCoder and initWithCoder methods. While I have not needed to do this or try this out, if myself or someone else happens to experiment with this with a good result please let me know and I'll add that example here.

For more information about creating a subclass by extending Objective-C classes in NativeScript, please check out this source: https://docs.nativescript.org/core-concepts/ios-runtime/how-to/ObjC-Subclassing

For more information about Objective-C classes in NativeScript, please read up here: https://docs.nativescript.org/core-concepts/ios-runtime/types/ObjC-Classes

Upvotes: 1

Related Questions