iOS WebKit - DataCloneError: The object can not be cloned - ios

When working with WKWebView of iOS WebKit, I encountered an error when I tried to postMessage back to my WKScriptMessageHandler in a code like
window.webkit.messageHandlers.thisHandler.postMessage(message);
where message is a Javascript object (or in iOS developer's eyes, a dictionary) and the error is:
WKJavaScriptExceptionMessage=DataCloneError: The object can not be cloned.
It was quite confusing what this is about and I couldn't google out any useful information.

After removing the key-values one by one from my message object, I eventually figured out this error is caused by my mistakenly including some Javascript DOM objects instead of their primitive values in the object. For example, I included some variable
const myVar = document.body.querySelector("div.someClassName")
in my message body, which cannot be cloned for the native Swift environment. Similarly window.location is a purely JS DOM object and not clone-able either. To fix, just get their primitive values and include that in the message, like
const myVar = document.body.querySelector("div.someClassName").innerText;
const myURL = window.location.href;
const message = {myVar, myURL};
window.webkit.messageHandlers.thisHandler.postMessage(message);

I had the same error for having a function in the message payload.

Related

JSON value '<null>' of type NSNull cannot be converted to NSString

I am getting the following error screen sometimes when I reload my React Native app in iOS Simulator.
Sometimes it doesn't happen at all but sometimes a few times during the day.
I am using SignalR client in my app as well as Firebase Messaging.
I have tried to put a try catch blocks to all of my app including where I use AsyncStorage but this is still happening.
Very frustrating.
my problem was with source of the images that i had in my component. i had tell the image components to pass null as source while response of the server for the image was empty or null. means:
<Image source={{uri: null}} style={styles.myImageStyle}/>
it was ok with android but in ios i ran into this error. so i changed my code to following and it's working fine now.
const imageUri = myImageUri!=null ? myImageUri : ""
<Image source={imageUri.length!=0?{uri: imageuri}: null} style={styles.myImageStyle}/>
I ran into this when using AsyncStorage. It can only store strings, so storing anything else won't work, like objects etc. Below is how I set and get an array of blocked users.
When you set your item, stringify it:
AsyncStorage.setItem('blocked_users', JSON.stringify(array));
Then when you read it from async storage, use a promise and json parse the data:
AsyncStorage.getItem("blocked_users")
.then((value) => {
if(value){
blocksArray = JSON.parse(value);
this.setState({ blocked_users: blocksArray});
};
});
Don't know if the OP got a solution but I have battled with this error and was able to come up with a solution. The error was originating from AsyncStorage. What I did to solve the issue was to use a conditional statement and set the default value to Null
componentDidMount() {
AsyncStorage.getItem('Key_0').then((value) =>
this.setState({getValue: value}))
}...
...var avatar
if(this.state.getValue == null){
avatar = require('path/to/palceholder/asset);
}else if(this.state.getValue ! = null){
avatar={uri: this.state.getValue};
}
<Image source={avatar}/> //the image source was the root cause of the error since Asyncstorage was passing null value
I hope this will help anyone looking for a solution in future.
my problem was with source of the profile image that i had in my component.
source={profileImage && profileImage ? {uri: profileImage} : null}
Check profile image is there and secondly add the condition.
Your issue is most likely due to something that wasn't defined in your native IOS code somewhere.
I received this error when I forgot to import a required package for React native IOS notifications in AppDelegate.m

NativeScript: Get string from interop.reference

To start, here is my code:
var buffer = malloc(interop.sizeof(interop.types.UTF8CString));
var fillBuffer = mac.getBytes(buffer);
var bytes = new interop.Reference(interop.types.UTF8CString, buffer);
var hexMac = bytes[0];
The variable 'Mac' is an NSData objected retrieved from CoreBluetooth. It is the scan response from a BLE device, which contains the peripheral's MAC address (00:0b:57:a2:fb:a0).
This problem is linked to THIS question I had posted earlier.
The solution provided is great; however, I cannot seem to implement this in nativescript :
(instancetype)stringWithFormat:(NSString *)format, ...;
Intellisense tells me the method doesnt exist on type NSString.
Due to that issue, I decided to go another route (as you can tell). I am filling a buffer with the bytes of the MAC address. In the code above, bytes[0] equates to 0xb57a2fba0.
I am now trying to convert that (which is an interop.Reference) into a string that I can store on the back-end (preferably in the xx:xx:xx:xx:xx format).
I have been at this all weekend, and cannot seem to find a solution. I even broke down objc!foundation.d.ts to figure out if stringWithFormat was supported, to no avail.
The nativescript community slack was unable to provide a resolution as well.
Please help if you can!
I don't know anything about NativeScript at all, but given the other code you wrote, I assume you're calling +alloc first, and so mean to use -initWithFormat: (an instance method that initializes) rather than +stringWithFormat: (a class method which handles allocation and initialization).

get mediaSessionID for the current media playing on chrome cast in Swift on iOS

I'm referring to https://developers.google.com/cast/docs/reference/ios/interface_g_c_k_media_status.html#a45e3eb39e674f5d0dbfd78deef77a1e6
that helps me with the api, but the initializer for the GCKMediaStatus class says:
- (instancetype) initWithSessionID: (NSInteger) mediaSessionID
mediaInformation: (GCKMediaInformation *) mediaInformation
note: this is in Objective-c syntax but Swift works just the same except in Swift language...
Nonetheless I can't seem to figure out how to retrieve the mediaSessionID to be able to initialize an instance of this class to a new variable.
I'm trying to do the following to get me eventually to the method within this class called streamPosition which would go like this:
var mediaStatus = GCKMediaStatus(sessionID: Int, mediaInformation: GCKMediaInformation!)
var currentStreamPosition = mediaStatus.streamPosition()
where Int would be the mediaSessionID NOT the sessionID of the chrome cast (read the additional section below!!) and GCKMediaInformation! would be an instance of the GCKMediaInformation class. (I think) correct me if I'm wrong on either of those parameters.
Then I could use this data. But when I do this the currentStreamPosition I suppose defaults to 0 and thats what I get when I print to the currentStreamPosition variable.
Note: I've already connected to the current playing media and I am able to pause, play, and seek to an arbitrary number within the stream. This all works. So I now I'm connected and everything else works.
use case: I want to be able skip ahead 15 seconds or rewind 15 seconds etc. with the use of this method, but I haven't found anything to help.
also - don't get sessionID confused with mediaSessionID!! I CAN get the sessionID successfully and print it out. My issue is with the mediaSessionID.
additional info: the autocomplete is Xcode says this is the parameters labeled names:
GCKMediaStatus(sessionID: Int, mediaInformation: GCKMediaInformation!)
note the first parameter says sessionID and it is of type int. But on https://developers.google.com/cast/docs/ios_sender if you notice sessionID is of type String! (an optional String).
I think this label was mis-named in Xcode for the autocomplete. I think it should be named mediaSessionID and NOT sessionID since this is what the documentation shows on the first link I provided.
Any help would be much appreciated.
Thanks!
To get the stream position, use the method approximateStreamPosition on GCKMediaControlChannel.

Replacement for DeviceInfo in phonegap > 1.5

It seems that they have deprecated the Phonegap variable DeviceInfo as of Cordova 1.5 (I think I saw that it was technically deprecated for 1.5 as well, but left it in). I know there is the device variable, but I was using the DeviceInfo variable to store some of my own data via the callback to
- (NSDictionary*)deviceProperties{...}
It seems that function is still called for the var device data, but it doesn't let me add any data to that variable. Does anyone know if there is anyway to get back the functionality of having custom device data or is it gone forever?
OK so the workaround I came up with was to simply create the variable myself in a javascript call so that the rest of the javascript code still access it as needed. I etd a catagory to override
- (void)viewDidAppear:(BOOL)animated;
and in the implementation I called the following code
NSString* jsString = [NSString stringWithFormat:#"window.DeviceInfo = {param1:%#, param2:%#}}", param1, param2];
[self.viewController.webView stringByEvaluatingJavaScriptFromString:jsString];
That added code allowed for backward compatibility with code based on the editable DeviceInfo variable that has been removed.

reading/writing preferences

I have read most all of the documentation and questions related to preferences I could find but I have an error that is always coming up no matter what method I try and I do not understand it.
js file loaded in browser overlay xul
var prefs = Components.classes["#mozilla.org/preferences-service;1"].
getService(Components.interfaces.nsIPrefService).
getBranch("extensions.{my-guid-id}.");
var value = prefs.getBoolPref("firstrun");
defaults/preferences/prefs.js:
pref("extensions.{my-guid-id}.firstrun", true);
The error message in the error console says uncaught exception: "compenent returned failure code 0x8000ffff" on line 27 which is right at getBoolPref() call.
Your code looks correct.
Are you sure that you did not put the word true in quotes or accidentally already set it as a non boolean preferences?
I would suggest going into about:config and verifying that your firstrun preference is showing up as a Boolean.
That's the most common cause of the problem you are seeing.

Resources