SVProgressHud waits too long to dismiss - ios

I want to display SVProgressHUD during login process. But SVProgressHUD still waits after login. It's dismissed ~15seconds after "Login success" message.
Here is my code:
[SVProgressHUD show];
__block BOOL result;
dispatch_async(queue, ^{
result = [self autanticate];
NSLog(#"autantication result = %d", result);
result = [self getCSRFToken];
NSLog(#"Login success result = %d", result);
[SVProgressHUD dismiss];
});
autanticate and getCSRFToken functions are like below:
- (BOOL) getCSRFToken
{
__block BOOL success = false;
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
// Make sure that the callbacks are not called from the main queue, otherwise we would deadlock
manager.requestSerializer = [AFJSONRequestSerializer serializer];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
NSDictionary *parameters = #{#"username": self.username.text,
#"password": self.password.text};
NSLog(#"Creating CSRF semaphore");
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
// CSRF Token bilgisini alalım
NSString *Url = [NSString stringWithFormat:#"%#%#", BaseURLString, #"?q=services/session/token"];
[manager GET:Url parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"CSRF Token: %#", responseObject);
success = true;
dispatch_semaphore_signal(semaphore);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
success = false;
dispatch_semaphore_signal(semaphore);
}];
NSLog(#"Waiting CSRF semaphore");
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
return success;
}
- (BOOL)autanticate
{
__block BOOL isAutanticated = false;
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
NSDictionary *parameters = #{#"username": self.username.text,
#"password": self.password.text};
// Session bilgilerini alalım
NSLog(#"Creating autantication semaphore");
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
NSString *Url = [NSString stringWithFormat:#"%#%#", BaseURLString, #"?q=rest/mserv/signin"];
[manager POST:Url parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
NSDictionary *result = [responseObject objectForKey:#"result"];
NSString *sessid = [result objectForKey:#"sessid"];
NSString *session_name = [result objectForKey:#"session_name"];
NSLog(#"sessid = %#\nsession_name=%#", sessid, session_name);
isAutanticated = true;
dispatch_semaphore_signal(semaphore);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
isAutanticated = false;
dispatch_semaphore_signal(semaphore);
}];
NSLog(#"Waiting autanticatio semaphore");
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
return isAutanticated;
}

You must dispatch [SVProgressHUD dismiss] to the main thread
[SVProgressHUD show];
__block BOOL result;
dispatch_async(queue, ^{
result = [self autanticate];
NSLog(#"autantication result = %d", result);
result = [self getCSRFToken];
NSLog(#"Login success result = %d", result);
dispatch_async(dispatch_get_main_queue(), ^{
[SVProgressHUD dismiss];
})
});
All user interface elements must only be modified on the main thread.
Remark: Note that the dispatch_async() returns
(almost) immediately, so that the result is not set
when dispatch_async() returns.
And don't be tempted to use a semaphore to wait for the block to finish.
That is fine on a background thread, but will most probably give a deadlock
on the main thread.

Related

Background upload of large number of images using AFNetworking

I am looking for uploading about 100 images in the background using AFNetworking ,do I need to create an operations queue? or I can create multiple request in a for loop like so:
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.responseSerializer.acceptableContentTypes = nil;
[manager.requestSerializer setTimeoutInterval:30.0];
for(MyImageView *myImageView in images){
NSDictionary *parameters = _PARAMETERS;
[manager POST:#"//MY_URL_" parameters:parameters
constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:UIImageJPEGRepresentation(myImageView.image, 0.65) name:#"NAME" fileName:#"name" mimeType:#"image/jpeg"];
}progress:^(NSProgress * _Nonnull uploadProgress) {
} success:^(NSURLSessionTask *task, id responseObject) {
NSDictionary *response = (NSDictionary *)responseObject;
dispatch_async(dispatch_get_main_queue(), ^{
int success = [[response objectForKey:#"success"] intValue];
if(success == 1) {
NSLog(#"IMAGE UPLOAD SUCCESSFULL");
}
else if (success == 0){
NSLog(#"IMAGE UPLOAD FAILED");
}
NSLog(#"%#",response);
});
} failure:^(NSURLSessionTask *operation, NSError *error) {
NSLog(#"%#",error.localizedDescription);
}];
}
How do I create an NSOperations Queue if need be?
Thanks
Use AFHTTPRequestOperation and NSOperarationQueue with NSOperationQueueDefaultMaxConcurrentOperationCount

Upload process blocks other requests AFNetworking 3.0

I am trying to upload data with AFNetworking and its successful. no problem with that but the problem is when I am doing it in background than the other requests blocks and doesn't give any response until upload progress finishes.
What I did is I made a singleton and declare AFURLSessionManager in that because I want all current running task.
+ (id)sharedInstance
{
static SharedManager *sharedMyManager = nil;
#synchronized(self) {
if (sharedMyManager == nil)
sharedMyManager = [[self alloc] init];
}
return sharedMyManager;
}
Let me tell you simple example.. for one controller, I made a request for upload process like below
ViewController1.m
-(void)postImage{
#try {
NSMutableDictionary *otherParameters = [[NSMutableDictionary alloc]initWithDictionary:_currentPlaceParameters];
[otherParameters setObject:[UtitlityManager getUserID] forKey:#"user_id"];
AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer];
NSMutableURLRequest *request =
[serializer multipartFormRequestWithMethod:#"POST" URLString:URL_UPLOAD_PHOTO_VIDEO parameters:otherParameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
NSData *thumbImageData = UIImageJPEGRepresentation(dataValue, 0.5);
[formData appendPartWithFileData:thumbImageData name:#"thumbnail" fileName:#"image.jpg" mimeType:#"image/jpeg"];
} error:nil];
//show progress bar on window
AFURLSessionManager *manager = [[SharedManager sharedInstance]manager];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
NSURLSessionUploadTask *uploadTask;
uploadTask = [manager uploadTaskWithStreamedRequest:request progress:^(NSProgress * _Nonnull uploadProgress) {
// This is not called back on the main queue.
// You are responsible for dispatching to the main queue for UI updates
float uploadActualPercentage = uploadProgress.fractionCompleted * 100;
NSLog(#"Multipartdata upload in progress: %#",[NSString stringWithFormat:#"%f %%",uploadActualPercentage]);
}
completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
if (error) {
} else {
NSDictionary *result=[NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingAllowFragments error:&error];
if([[result objectForKey:#"success"] integerValue]==1){
}else{
[Common showMessageWithMessage:#"Failed, Try again"];
}
}
}];
[uploadTask resume];
} #catch (NSException *exception) {
NSLog(#"EXC: %#",[exception description]);
}
}
And than I try to move another view controller and send a request for get other data ...
ViewController2.m
-(void)getData{
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[manager POST:url parameters:parameters progress:nil success:^(NSURLSessionTask *task, id responseObject) {
NSDictionary* responseDict = [NSJSONSerialization JSONObjectWithData:responseObject options:kNilOptions error:nil];
} failure:^(NSURLSessionTask *operation, NSError *error) {
}];
}
But this doesn't give response until progress finishes... why so??
Even I try to set this upload process in dispatch_sync but it won't work ... any suggestion on this???

Do something in the same thread of AFNetworking

I'm using Objective-C. We know AFNetworking is working in another thread, but what if I want to do something after internet request.
For example:
- (BOOL)checkPassword
{
self.loginPermit = NO;
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"text/html"];
NSDictionary *parameters = #{#"username": self.username, #"password": self.password};
[manager POST:self.URL parameters:parameters progress:nil
success:^(NSURLSessionDataTask *task, id responseObject)
{
NSDictionary *dict = (NSDictionary *)responseObject;
if ([[dict objectForKey:#"msg"] isEqualToString:#"00001"]){
self.loginPermit = YES
}
else {
self.loginPermit = NO;
}
} failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog(#"Error: %#", error);
}];
return self.loginPermit;
}
But it will return NO every time. How can I return the value after Internet request.
You should use block for this.
[self checkPassword:^(BOOL loginPermit) {
if(loginPermit){
// do your stuff
}
}];
- (void)checkPassword:(void(^)(BOOL loginPermit))completion
{
BOOL loginPermit = NO;
// show indicator
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:#"text/html"];
NSDictionary *parameters = #{#"username": self.username, #"password": self.password};
[manager POST:self.URL parameters:parameters progress:nil
success:^(NSURLSessionDataTask *task, id responseObject)
{
//hide indicator
NSDictionary *dict = (NSDictionary *)responseObject;
if ([[dict objectForKey:#"msg"] isEqualToString:#"00001"]){
loginPermit = YES;
}
else {
loginPermit = NO;
}
completion (loginPermit);
} failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog(#"Error: %#", error);
//hide indicator
completion (loginPermit);
}];
}

AFNetworking iOS - way to see actual data in NSLog after GET request is complete

I have a simple call to an api method below called queryJobAndMoveWithName that makes GET request (ex. http://www.imdb.com/xml/find?json=1&nr=1&nm=on&q=jennifer).
However when I look at the log responseJSON gets rendered as <57652068 6f706520 746f206c 61756e63 68205353 4c206163 63657373 20746f20 616c6c20 70616765 73206f6e 20494d44 6220696e 20746865 20766572 79206e65 61722066 75747572 652e0d0a 0d0a5468 616e6b73 20666f72 20796f75 72207061 7469656e 63652e> other than {XXX:XXX, XXX:XXX}
- (void)queryJobAndMoveWithName:(NSString *)name completionHandler:(void (^)(NSDictionary *resultsJSON, NSError *error))completionHandler {
NSString *url = [NSString stringWithFormat:#"%#%#?json=1&nr=1&nm=on&q=%#", kAPIHost, kSearchPath, name];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.requestSerializer = [AFHTTPRequestSerializer serializer];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:#"application/json", #"text/javascript" ,#"text/html", #"text/plain", #"text/json", nil];
[manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseJSON) {
NSLog(#"JSON: %#", responseJSON);
completionHandler(responseJSON, nil);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
completionHandler(nil, error);
}];
}
Here is a method that calls the api method from view controller
- (IBAction)searchButtonTapped:(id)sender {
NSLog(#"%#",self.searchTextField.text);
NSString *queryName = self.searchTextField.text;
NSArray *fullName = [queryName componentsSeparatedByString:#" "];
NSString *formattedFullName = [fullName componentsJoinedByString:#"+"];
FPAImdbApi *imdbApi = [[FPAImdbApi alloc] init];
[imdbApi queryJobAndMoveWithName:formattedFullName completionHandler:^(NSDictionary *resultsJSON, NSError *error) {
if (error) {
NSLog(#"error: %#", error);
} else if (resultsJSON) {
NSLog(#"result json: \n %#", resultsJSON);
} else {
NSLog(#"nothing found");
}
}];
}
so my question is how do I view the contents of the resulting JSON in logs other than the form of memory
You have not told the manager that the response is in JSON, here you set the response serializer to HTTP:
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
Chang it to JSON:
manager.responseSerializer = [AFJSONResponseSerializer serializer];
In the error block you could do something like this to print out the response from the server:
if (error) {
NSHTTPURLResponse *respone = error.userInfo[AFNetworkingOperationFailingURLResponseErrorKey];
NSData *errorData = error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey];
NSString *responseString = [[NSString alloc] initWithData:errorData encoding:NSUTF8StringEncoding];
NSLog(#"Response: %#", responseString);
}

Trying to make a function to handle AFNetworking

I'm trying to make a function that I'll call to handle the AFNetworking JSON parse.
Here is my code:
- (int)startParseWithParameters:(NSDictionary*)incomingParameters andUrlAdress:(NSString*)urlAdress;
{
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
NSDictionary *parameters = incomingParameters;
[manager POST:urlAdress parameters:parameters success:^
(AFHTTPRequestOperation *operation, id responseObject)
{
NSString *recivedErr = responseObject[#"error"];
_errValue = [recivedErr intValue];
NSLog(#"JSON: %d", _errValue);
}
failure:^(AFHTTPRequestOperation *operation, NSError *error)
{
NSLog(#"Error: %#", error);
}];
return _errValue;
}
I want the function to return 0 or 1, then I'll know if there is an error or not.
Right now it always return 0.
When I try to return in the success block I get a compiler error.
What could cause this problem?
The succes block is handled async so you should just call a method in the block:
- (void)startParseWithParameters:(NSDictionary*)incomingParameters andUrlAdress:(NSString*)urlAdress {
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
NSDictionary *parameters = incomingParameters;
__weak typeof(self) weakSelf = self;
[manager POST:urlAdress parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSString *recivedErr = responseObject[#"error"];
[weakSelf didReceiveResponse:[recivedErr integerValue];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
}
-(void)didReceiveResponse:(NSInteger)status {
}

Resources