I have the following AcceptCallBack
method and was hoping to add an UIActivityIndicator while the method is running, hence the [mvc performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:YES];
. invoke
is the method which makes the UI changes. And then I have this line [mvc performSelectorOnMainThread:@selector(hide) withObject:nil waitUntilDone:YES];
to remove the UIActivityIndicator. However what seem to happen is that invoke only gets called when AcceptCallBack
has finished executing. Are AcceptCallBack
and invoke
not running on two different threads, therefore allowing them to run simultaneously??
void AcceptCallBack(
CFSocketRef socket,
CFSocketCallBackType type,
CFDataRef address,
const void *data,
void *info)
{
NSLog(@"Start Receiving...");
MasterViewController* mvc = (__bridge MasterViewController*)info;
[mvc performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:YES];
CFReadStreamRef readStream = NULL;
CFWriteStreamRef writeStream = NULL;
CFIndex bytes;
UInt8 buffer[8192];
UInt8 * fileData;
UInt8 recv_len = 0;
/* The native socket, used for various operations */
CFSocketNativeHandle sock = *(CFSocketNativeHandle *) data;
/* Create the read and write streams for the socket */
CFStreamCreatePairWithSocket(kCFAllocatorDefault, sock,
&readStream, &writeStream);
if (!readStream || !writeStream) {
close(sock);
fprintf(stderr, "CFStreamCreatePairWithSocket() failed\n");
return;
}
CFReadStreamOpen(readStream);
CFWriteStreamOpen(writeStream);
bool headerRead = false;
int dataWritten = 0;
NSMutableString* filename = NULL;
NSMutableString * header = [[NSMutableString alloc] init];
while (true) {
memset(buffer, 0, sizeof(buffer));
bytes = CFReadStreamRead(readStream, buffer, sizeof(buffer));
recv_len += bytes;
if (bytes < 0) {
fprintf(stderr, "CFReadStreamRead() failed: %d\n", (int)bytes);
close(sock);
return;
}
if (bytes == 0) {
break;
}
if (!headerRead) {
for (int b=0; b<bytes; b++) {
if (buffer[b] == '\n') {
headerRead = true;
NSLog(@"Header is: %@", header);
NSArray *listItems = [header componentsSeparatedByString:@":"];
filename = [[NSMutableString alloc] init];
[filename appendString:[listItems objectAtIndex:2]];
[filename replaceOccurrencesOfString:@"/" withString:@"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [filename length])];
fileData = (UInt8*)malloc(sizeof(UInt8) * [[listItems objectAtIndex:3] intValue]);
b++;
memcpy(fileData, buffer + b, bytes - b);
dataWritten = bytes - b;
break;
} else {
[header appendFormat:@"%c", buffer[b]];
}
}
} else {
memcpy(fileData + dataWritten, buffer, bytes);
dataWritten += bytes;
}
}
NSString* docFile = [NSTemporaryDirectory() stringByAppendingPathComponent:filename];
NSData * outputData = [[NSData alloc] initWithBytes:fileData length:dataWritten];
if ([outputData writeToFile:docFile atomically:false] == YES) {
NSLog(@"File received and successfully written out to file------------------------------");
MasterViewController * thing = (__bridge MasterViewController*)info;
[thing restClient:NULL loadedFile:docFile];
NSString *destDir = @"/Slide2Me/";
[[thing restClient] uploadFile:filename toPath:destDir
withParentRev:nil fromPath:docFile];
[mvc performSelectorOnMainThread:@selector(hide) withObject:nil waitUntilDone:YES];
} else {
NSLog(@"Failed to write received data to file");
}
}
EDIT
So what I ended up doing to get my desired result is put all the above code in dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)
and sandwich it with the changes I want to make on the main thread like so....
void AcceptCallBack(
CFSocketRef socket,
CFSocketCallBackType type,
CFDataRef address,
const void *data,
void *info)
{
NSLog(@"Start Receiving...");
MasterViewController* mvc = (__bridge MasterViewController*)info;
[mvc performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:YES];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
[the code above];
});
[mvc performSelectorOnMainThread:@selector(hide) withObject:nil waitUntilDone:YES];
}