Reputation: 11076
I'm trying to port the following method to RubyMotion
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSInteger dataLength = [data length];
const uint8_t * dataBytes = [data bytes];
NSInteger bytesWritten;
NSInteger bytesWrittenSoFar;
bytesWrittenSoFar = 0;
do {
bytesWritten = [self.downloadStream write:&dataBytes[bytesWrittenSoFar] maxLength:dataLength - bytesWrittenSoFar];
assert(bytesWritten != 0);
if (bytesWritten == -1) {
[self cleanupConnectionSuccessful:NO];
break;
} else {
bytesWrittenSoFar += bytesWritten;
}
} while (bytesWrittenSoFar != dataLength);
self.progressContentLength += dataLength;
}
(it's from robertmryan/download-manager)
This is what I have currently, which crashes on the call to downloadStream with connection:didReceiveData:': can't convert Fixnum into String (TypeError)
def connection(connection, didReceiveData:data)
dataLength = data.length
dataBytes = data.bytes
bytesWritten = 0
bytesWrittenSoFar = 0
begin
maxLength = dataLength - bytesWrittenSoFar
buffer = dataBytes[bytesWrittenSoFar]
bytesWritten = self.downloadStream.write buffer, maxLength: maxLength # CRASH
if bytesWritten == -1
self.cleanupConnectionSuccessful false
break
else
bytesWrittenSoFar += bytesWritten
end
end while bytesWrittenSoFar != dataLength
self.progressContentLength += dataLength
if self.delegate.respondsToSelector('downloadDidReceiveData:')
self.delegate.downloadDidReceiveData(self)
end
end
I realise that my conversion ignores the pointers is likely naive and wrong. I've checked the RubyMotion docs, but they are a bit sparse, and my understanding of C isn't strong enough to know how to apply it here. Some advice would be much appreciated.
Upvotes: 4
Views: 528
Reputation: 3319
The bytes
method of NSData
returns a Pointer
type (http://www.rubymotion.com/developer-center/api/Pointer.html).
The []
method in the Pointer
type gives you access to element at that position from the start of the pointer. It seems to me that bytes
returns a Pointer
of type “C” (unsigned char), so when you try to access the Pointer
like dataBytes[bytesWrittenSoFar]
you where only obtaining a Fixnum
which was the value of that byte from the start of the pointer.
To do what you want to do you will need something like the following:
bytesWrittenSoFar = 0
begin
maxLength = dataLength - bytesWrittenSoFar
buffer = dataBytes + bytesWrittenSoFar
bytesWritten = self.downloadStream.write buffer, maxLength: maxLength
if bytesWritten == -1
self.cleanupConnectionSuccessful false
break
else
bytesWrittenSoFar += bytesWritten
end
end while bytesWrittenSoFar != dataLength
I haven’t run it, but I hope it works.
Upvotes: 4