Swift Create Byte Buffer Holder for Nsstream

swift create byte buffer holder for NSStream

You can use a use an Array<UInt8> as the buffer and pass it as it is documented in Using Swift with Cocoa and Objective-C:

let bufferSize = 1024
var buffer = Array<UInt8>(count: bufferSize, repeatedValue: 0)

let bytesRead = inputStream.read(&buffer, maxLength: bufferSize)
if bytesRead >= 0 {
var output = NSString(bytes: &buffer, length: bytesRead, encoding: NSUTF8StringEncoding)
} else {
// Handle error
}

-[NSInputStream read:maxLength:] returns a number indicating how many bytes it read (if it's >= 0) or if there was an error (if it's negative). You should check the return value accordingly.

Stream to Get Data - NSInputStream

There are two ways to get data from a stream: polling and using stream events.

Polling is simpler, but will block the thread it is running in. If you use this method, you don't need to perform the setDelegate: or scheduleInRunLoop:forMode: calls. Polling is performed by repeatedly calling read:maxLength:.

NSInteger result;
uint8_t buffer[BUFFER_LEN]; // BUFFER_LEN can be any positive integer
while((result = [iStream read:buffer maxLength:BUFFER_LEN]) != 0) {
if(result > 0) {
// buffer contains result bytes of data to be handled
} else {
// The stream had an error. You can get an NSError object using [iStream streamError]
}
}
// Either the stream ran out of data or there was an error

Using stream events requires setting the delegate and adding the stream to a run loop. Instead of blocking the thread, the stream will send a stream:handleEvent: message to its delegate when certain events occur, including when it receives data. The delegate can then retrieve the data from the stream. Here is an example stream:handleEvent: method:

- (void)stream:(NSInputStream *)iStream handleEvent:(NSStreamEvent)event {
BOOL shouldClose = NO;
switch(event) {
case NSStreamEventEndEncountered:
shouldClose = YES;
// If all data hasn't been read, fall through to the "has bytes" event
if(![iStream hasBytesAvailable]) break;
case NSStreamEventHasBytesAvailable: ; // We need a semicolon here before we can declare local variables
uint8_t *buffer;
NSUInteger length;
BOOL freeBuffer = NO;
// The stream has data. Try to get its internal buffer instead of creating one
if(![iStream getBuffer:&buffer length:&length]) {
// The stream couldn't provide its internal buffer. We have to make one ourselves
buffer = malloc(BUFFER_LEN * sizeof(uint8_t));
freeBuffer = YES;
NSInteger result = [iStream read:buffer maxLength:BUFFER_LEN];
if(result < 0) {
// error copying to buffer
break;
}
length = result;
}
// length bytes of data in buffer
if(freeBuffer) free(buffer);
break;
case NSStreamEventErrorOccurred:
// some other error
shouldClose = YES;
break;
}
if(shouldClose) [iStream close];
}

Why is the HTTPBody of a request inside an NSURLProtocol Subclass always nil?

Here's a sample code for reading the httpBody:

Swift 5

extension URLRequest {

func bodySteamAsJSON() -> Any? {

guard let bodyStream = self.httpBodyStream else { return nil }

bodyStream.open()

// Will read 16 chars per iteration. Can use bigger buffer if needed
let bufferSize: Int = 16

let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bufferSize)

var dat = Data()

while bodyStream.hasBytesAvailable {

let readDat = bodyStream.read(buffer, maxLength: bufferSize)
dat.append(buffer, count: readDat)
}

buffer.deallocate()

bodyStream.close()

do {
return try JSONSerialization.jsonObject(with: dat, options: JSONSerialization.ReadingOptions.allowFragments)
} catch {

print(error.localizedDescription)

return nil
}
}
}

Then, in URLProtocol:

override func startLoading() {

...

if let jsonBody = self.request.bodySteamAsJSON() {

print("JSON \(jsonBody)")

}

...
}

Playing Audio on iOS from Socket connection

I solved this in the end, see my answer here

I intended putting the code here, but it would be a lot of copy pasting

iOS send data using socket connection

After doing hard research i found adding \n at the end of string message indicates my buffer has received whole string.
now start sending a file, so it worked...

To send a String over Sockets, you must mark the end of the string. ie; Add a \n



Related Topics



Leave a reply



Submit