I have a registration view controller which handles all the user input and calls a function in another class (wsClass) passing to it, that data as an NSDictionary.
T
The post completes asynchronously, so your wsClass needs to tell the caller about completion after post is finished.  A nice way to do this is to augment the sendData method with a block of code supplied by the caller that should be run upon completion:
Change sendData: to look like this:
// it doesn't return anything, because all it does is launch the post
// but when the post is done, it invokes completion
- (void)sendData:(NSDictionary *)sendDict completion:(void (^)(NSDictionary *))completion {
    // the stuff you're already doing
        NSURLSessionDataTask *postDataTask = [session dataTaskWithRequest:request
            completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
            // the stuff you're already doing
            // now tell the caller that you're done
            completion(jsonArray);
        }];
    }
The caller now looks like this:
// change the UI to say "I'm busy doing the post"
[ws sendData:testDict completion:^(NSDictionary *responseDict) {
    NSLog(@"this runs later, after the post completes %@", responseDict);
    // change the UI to say "The post is done"
}];
Just a couple of notes about this: (1) I didn't add an error param to the block, you probably should. Check that and invoke the block with either nil and an error, or with the json output and error=nil. (2) Your code assumes that the json result parses as a dictionary. Make sure that's always true before you assume it in code. (3) Class names usually begin with caps.