I am working with a package called DSBridge to connect a mobile application (iOS code in this case) to javascript code containing the main logic of my application. This involves running the JavaScript on an invisible WKWebView.
My JavaScript code needs to call a method in the native iOS application which needs to execute and return a value to the JavaScript.
My Objective C function reads:
- (NSString* )read:(NSDictionary *) args{
NSLog(@"In Read");
while(self->connection != NULL) {
if([self->connection isMessageAvailable]) {
[self->connection messageRetrieved];
NSLog(@"Message Received in ViewController");
return [self->connection getMessage];
}
}
return NULL;
}
Which is called from my JavaScript, I need this to return on the main thread so that the return value is sent into my WebView.
The issue is that my the message from IO I am waiting for will never appear as my NSStream is blocked by the while loop.
My connection methods and NSStream look like this:
-(void)readData:(NSData*)receivedData{
NSData *decoded = [self btXOR:receivedData withMask:0x26];
message = [[NSString alloc] initWithData:decoded encoding:NSUTF8StringEncoding];
NSLog(@"message: %@", message);
messageAvailable = true;
}
- (BOOL) isMessageAvailable {
return messageAvailable;
}
- (void) messageRetrieved {
messageAvailable = false;
}
- (NSString*) getMessage {
NSLog(@"Message: %@", message);
return message;
}
#pragma mark StreamDelegate
-(void) stream:(NSStream *)theStream handleEvent:(NSStreamEvent)eventCode
{
switch (eventCode)
{
//Reading in from host done here
case NSStreamEventHasBytesAvailable:
DDLogInfo(@"NSStreamEventHasBytesAvailable");
DDLogInfo(@"stream is input: %i " , (theStream == inputStream));
NSLog(@"NSStreamEventHasBytesAvailable");
NSLog(@"stream is input: %i " , (theStream == inputStream));
if (theStream == inputStream)
{
uint8_t buffer[1024];
long len;
while ([inputStream hasBytesAvailable])
{
len = [inputStream read:buffer maxLength:sizeof(buffer)];
DDLogDebug(@"InputStream still has bytes");
NSLog(@"InputStream still has bytes");
if (len > 0)
{
NSMutableData* data=[[NSMutableData alloc] initWithLength:0];
[data appendBytes: (const void *)buffer length:(int)len];
[self readData:data];
}
}
}
break;
The 'NSStreamEventHasBytesAvailable' case should occur once the message is ready, and should be picked up by my read function so it can be returned to my WebViews JavaScript.
How can I take the while loop off of the main thread and still return once I have the message? Is it possible to take the NSStream off the main runloop in a way that it will not be blocked by my read function?
I tried making read async and using a callback to the JavaScript as seen here, but this makes my JavaScript codebase rather unwieldy with callbacks.