Question

I have a code design question, I'm having trouble thinking of the most efficient manner to handle this:

Basically, I want to send a JSON request and read the response back from the server in one go.

I have a methods such as:

-(BOOL)sendString:(NSString *)sendString;
//This should return a NSString and a BOOL
-(NSDictionary *)loginRequestWithEmail:(NSString *)userEmail andPassword:(NSString     *)userPassword;
//This should return a NSString and a BOOL
-(NSDictionary *)requestNewUserAccountWithDisplayName:(NSString *)displayName Email:    (NSString *)userEmail andPassword:(NSString *)userPassword;

I'll explain what

-(BOOL)sendString:(NSString *)sendString;

does, Basically sends a JSON string to the server and gets a response of wether it failed or not.

I know how to write this to the server and read this. The issue is with doing this together, so I can return that BOOL value as a true or false to see if it worked.

Now after writing to a socket, I get a response and must read it through a delegate method:

-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {

Which is called as soon as the server gives a response. The issue is, all this reading/writing to the socket happens asynchronously.

Since that happens, I can't have a method that does this:

-(BOOL)sendString:(NSString *)sendString{

NSError *error;

NSLog(@"Sending String: %@",sendString);

NSDictionary *blobData = [NSDictionary dictionaryWithObjectsAndKeys:
                          sendString,@"string",
                          nil];
NSString *blobString = [[NSString alloc]
                        initWithData:[NSJSONSerialization dataWithJSONObject:blobData options:kNilOptions error:&error]
                        encoding:NSUTF8StringEncoding];
NSLog(@"Blob Created: %@", blobString);
NSDictionary *requestData = [NSDictionary dictionaryWithObjectsAndKeys:
                             @"send_string",@"request_type",
                             [NSNumber numberWithInt:0],@"security_level",
                             @"ios",@"device_type",
                             //No Email Provided, This is just for testing
                             blobString,@"blob",
                             nil];

NSData *JSONRequestData = NULL;
JSONRequestData = [NSJSONSerialization dataWithJSONObject:requestData options:kNilOptions error:&error];
        NSLog(@"Contents of JSONRequestData: %@",[[NSString alloc] initWithData:JSONRequestData encoding:NSUTF8StringEncoding]);
JSONRequestData = [[[[NSString alloc] initWithData:JSONRequestData encoding:NSUTF8StringEncoding] stringByAppendingString:@"\\n"] dataUsingEncoding:NSUTF8StringEncoding];
//Write the data
NSMutableData *JSONRequestDataWithLineEnding = [[NSMutableData alloc] initWithData:JSONRequestData];
[JSONRequestDataWithLineEnding appendData:[GCDAsyncSocket CRLFData]];
[asyncSocket writeData:JSONRequestDataWithLineEnding withTimeout:-1 tag:1];

//read a response
[asyncSocket readDataWithTimeout:-1 tag:2];

//This should be done in the didRead delegate
NSString *failure = [serverJSONResponseParsed objectForKey:@"failure"];
NSLog(@"Contents of string failure: %@", failure);

if ([failure isEqualToString:@"none"]) {
    NSLog(@"Success Sending String");
    return TRUE;
}
else {
    NSLog(@"Failure: %@",failure);
    return FALSE;
}

}

Since the code that is called after

[asyncSocket readDataWithTimeout:-1 tag:2];

executes before the data is read (because it's all async).

I realize I must do something in that delegate method. Which is fine, but I have different types of responses coming in, and each response must be handled differently.

My idea is: tag each of the write commands, and then use some

if(this_tag) {do this} ....else if(that_tag) {do this} ....

in the didReadData delegate method.

But how do I return this data correctly? Sometimes I need to return a BOOL, other times I need to return an NSDictionary, NSString, etc...

I would love to be able to have each of my request methods mentioned above return their associated data, but I can't (at least not efficiently). Do I have to make two different methods for each request?

i.e.

sendString
getSendStringResponse

I'm a little confused as to how to handle this.

I apologize if I'm not being clear,

I appreciate any help that I can get.

Was it helpful?

Solution

What I would do is to create some type of protocols for this particular app. For example, let's say you have the following data types (not related to Obj-C) dat1, dat2, dat3, etc that this app needs to send and get the appropriate response back as res1, res2, res3, etc. You would come up with a signature for each data type for the sending part as well as for the responding part. Before sending each data, you need to prefix the data with the signature. On the receiver end using readDataWithTimeout, in the didReadData callback method, extract the header for the received data and the decide the response based on the protocols that you have agreed/designed earlier. There are other additional steps before this is complete design. For example, as part of your header info it might contain other info such as length of data, etc. Hope this will help you get started.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top