Quickblox: Custom Module - Custom callback function instead of default 'completedWithResult' - quickblox

When using 'Custom Module', there are times when multiple asynchronous requests happen at the same time (handled by the same delegate) and there is a need to distinguish which request triggered the 'completedWithResult' callback.
Is there a way to provide a custom callback function for a particular request? If not, what would be the best way to distinguish between multiple requests inside the 'completedWithResult'callback?

You should use context
[QBUsers logInWithUserLogin:#"injoitUser1" password:#"injoitUser1" delegate:self context:#"thisIsPoint1"];
[QBUsers logInWithUserLogin:#"injoitUser1" password:#"injoitUser1" delegate:self context:#"thisIsPoint2"];
- (void)completedWithResult:(Result *)result context:(void *)contextInfo{
if([result isKindOfClass:QBUUserLogInResult.class]){
if(result.success){
if([((NSString *)contextInfo) isEqualToString:#"thisIsPoint1"]){
// do smthn
}
}
}

Related

iOS: Waiting for API Completion Block and returning the result

Using inheritance.
I have a child class that calls a method in the parent class that runs calls the server API.
-(IBAction)buttonPressed
{
[self methodInParentClassThatCallsTheAPI:param];
// This is where I would like the call back
if (success from the server API) // do something with the UI
else if (failure from the server API) // do so something else with the UI
}
Parent Class:
- (void)methodInParentClassThatCallsTheAPI:(NSString *)param
{
//The method below calls the server API and waits for a response.
[someServerOperation setCompletionBlockWithSuccess:^(param, param){
// Return a success flag to the Child class that called this method
} failure:^(param, NSError *error){
// Return a failure flag to the Child class that called this method
}
}
How can I accomplish this with a block? Is there a better way to do this other than the block? Code example please
Create a completion block on methodInParentClass like this:
- (void)methodInParentClassThatCallsTheAPI:(NSString *)param completionBlock:(void (^)(BOOL success))completionBlock;
Then fire it inside the block success/failure with the appropriate value like this:
completionBlock(YES);
EDIT: By the way, please note that the return may not be on the main thread so if you plan to do a UI update you can fire the return block with a dispatch_async(dispatch_get_main_queue, ^{});
EDIT2: Since you seem to suggest this is the result of a button tap if your child is a VC waiting on the return just remember that this block will return async (obviously since that's what it is designed for) so if you need to hold the user for whatever reason you'll need to have the main thread display a loading indicator of some sort and hold user input events. Just remember that if you don't the UI will continue responding when before the completion block fires so at the very least you will want to disable the button so the user can't multi-press it and then you can reenable it when the completion block fires from the child VC.
EDIT3: Ok here is the calling code.
-(IBAction)buttonPressed
{
[self methodInParentClassThatCallsTheAPI:param withCompletionBlock:^(BOOL success){
if (success) {
// do something with the UI
} else {
// Do something else
}
}];
}

Terminating all methods in a cocoa app and re-initing

I want to terminate all currently called methods and then simply re-init my current object.
So when the user clicks on say the Start button, I call a bunch of methods...start doing stuff. Then when the user clicks on Cancel, i need to simply stop all running tasks/methods and re-init.
I don't want the app itself to terminate. So cannot use [NSApp terminate:nil]. I just need all current functions to stop and then i can call [self init];
Thanks in advance.
First, you have to set some flag and disable your user interface until all methods are completed. For example, self.cancelled = YES.
Next, each of your methods should be adjusted to return if that flag is set:
- (void)doSomething
{
if (self.cancelled) return;
// ...
for (/* ... */) {
// ...
if (self.cancelled) return;
// ...
}
// etc...
}
Then, you need a mechanism to track all your methods. Most likely, you will use NSOperationQueue or dispatch_queue_t. Take a look into documentation to find out how to get a notification when the queue becomes empty.
Finally, reset the self.cancelled flag and unblock your user interface.

Checking for NSRunLoop and using appropriate NSURLConnection method

I'm working on a personal project and ran into the asynchronous nature of NSURLConnection last night. I'm building a library that is going to interface with a restful api. I'm anticipating reusing this library, in both Foundation command line tools as well as Cocoa applications.
Is there a way I can either check if the runloop is available to call the synchronous method if it is, and send a synchronous request if it is not (in the event of being used in a command line tool).
Alternately, is there a way to always use the asynchronous method but force the application to not exit until the async request has finished?
I noticed this but I'd rather not have to put the call to run outside of the library.
Thanks for any help
Alternately, is there a way to always use the asynchronous method but force the application to not exit until the async request has finished?
Easy as pie:
int main(int argc, char *argv[])
{
// Create request, delegate object, etc.
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request
delegate:delegate
startImmediately:YES];
CFRunLoopRun();
// ...
}
I use CFRunLoopRun() here because it's possible to stop it later, when the delegate has determined that the connection is done:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
// This returns control to wherever you called
// CFRunLoopRun() from.
CFRunLoopStop(CFRunLoopGetCurrent());
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(#"Error: %#", error);
CFRunLoopStop(CFRunLoopGetCurrent());
}
The other option is to use -[NSRunLoop runUntilDate:] in a while loop, and have the delegate set a "stop" flag:
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request
delegate:delegate
startImmediately:YES];
while( ![delegate connectionHasFinished] ){
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1];
}
I suppose you can check if the program is linked against AppKit by seeing if NSClassFromString(#"NSApplication") returns non-Nil. Then, you can check if you're on the main thread using +[NSThread isMainThread].
However, it's poor design for the library to try to "force" the app not to exit for whatever reason. Just establish that the library requires the cooperation of the app and provide a cleanup-and-finish routine for it to call. Possibly also a is-there-something-in-progress? function.

iOS threading - callback best practice

I wanted to clean up one of my projects and extracted parts of my source that I often reuse, in a single class.
This class handles some requests to a web service, everything is fine so far ;). Until I extracted the code to its own class, I handled those requests with threads and callbacks in the calling class.
Now I have a "best practice" question:
In my code I do something like(simplified):
(void)foo{
Helper *h =[[Helper alloc]init];
[h doRequest];
}
doRequest performs a network action(in its own class)and I have to wait until this is request is finished. So I need a callback or something like this.
Should I simply thread doRequest incl. waituntildone=YES?
Do I have to thread the networking in the Helper class too? Or is it enough to call the method threaded something like this:
[NSThread detachNewThreadSelector:#selector(h doRequest) toTarget:self withObject:nil];
What is the best practice to get a callback from doRequest to the caller class after it has completed it’s tasks so that I can handle the returned values from the web service?
Thanks in advance.
Johannes
Given doRequest does not return until the request is done you could do
- (void)fooCompletion:(void (^)(void))completion {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
Helper *h =[[Helper alloc]init];
[h doRequest];
if (completion) {
dispatch_async(dispatch_get_main_queue(), ^{
// doRequest is done
completion();
});
}
});
}
To call the method:
[self fooCompletion:^{
// do something after doRequest is done
}];
I personally prefer calling performSelectorOnMainThread:withObject:waitUntilDone: at the end of any helper threads that need to send information back.
[self performSelectorOnMainThread:#selector(infoFromService:) withObject:aDictionaryWithInfo waitUntilDone:NO];
- (void)infoFromService:(NSDictionary *)aDictionary {
//Process all the information and update UI
}
Be sure to always use the main thread for any UI updates even if they happen in the middle of the worker thread, for example updating a count of how much information has been downloaded. Use the same technique to call the main thread with the relevant information.

Objective-C fast enumeration and asynchronous server operations. Model help?

If I have a method called "-uploadToServer:(Object *)objectToUpload", and a mutable array of several Objects, and I want to upload each object one after the other, how could I best handle this?
There are three important considerations:
Don't want NSOperation because I don't want to deal with threading issues
Need to wait for notification of task completion before continuing
Server calls are asynchronous and non-blocking
Here is some code I already have:
for (Object *task in objectsToUpload) {
[self uploadToServer:task];
//need to wait to get notification that upload completed
}
-(void)uploadToServer:(Object *)objectToUpload {
//perform asynchronous server operation here
//either block callback or delegate to notify
//self that upload finished
}
Seeing the above, how do you think I should handle this?
Don't want NSOperation because I don't want to deal with threading issues
Honestly, I think this is your easiest option. The only other way is to do asynchronous IO and use the run loop.
With NSOperation, you'd need two different kinds of operation called e.g. UploadOperation and NotifyOperation: one to upload an object and one to send a notification to the main thread when everything is done.
Then you'd loop through thwe objects putting them all on an NSOperationQueue in an UploadOperation, each one dependent on the previous one (addDependency:). Finally, you'd put the NotifyOperation on the queue dependent on the last UploadOperation.
The NotifyOperation overrides main as follows
-(void) main
{
[someObjectEgViewController performSelectorOnMainThread: #selector(finishedUpload)
withObject: nil
waitUntilDone: NO];
}
objectsToUpload is an NSMutableArray of tasks
-(void)uploadToServer{
//check if there is a task available
if (objectsToUpload.count > 0){
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
//get first task
id nextTask = [objectsToUpload objectAtIndex:0];
//do something
//complete async
dispatch_async(dispatch_get_main_queue(), ^(void) {
//remove completed task
[objectsToUpload removeObject:nextTask];
//complete async upload task, check or notify and or start the next task
BOOL shouldDoNextTask = [self check];
if (shouldDoNextTask){
[self uploadToServer];
}
});
});
}
}
I would suggest you do not need to wait for the task to complete. What you need is to respond to the task's completion.
NSURLConnection will provide a delegate with callback methods.