NSXMLParser parserDidStartDocument freezes app - ios

I tried to add some operations after call
- (void)parserDidStartDocument:(NSXMLParser *)parser {
//NSLog(#"found file and started parsing");
alertView = [[UIAlertView alloc] initWithTitle:#"Caricamento..."
message:#"\n"
delegate:self
cancelButtonTitle:nil
otherButtonTitles:nil];
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
spinner.center = CGPointMake(139.5, 75.5); // .5 so it doesn't blur
[alertView addSubview:spinner];
[spinner startAnimating];
[alertView show];
}
But it freeze the app for a while, and then, when finished the XML parse, loads the AlertView, ecc. Same thing with the UIRefreshControl. I slide down the tableView, and the app freeze while parsing, I cant see the spinner rotating.
Any idea?
Edit:
here I call the first time the parser:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSString * path = #"thexmlpath.xml";
if(!caricato)
[NSThread detachNewThreadSelector:#selector(parseXMLFileAtURL:) toTarget:self withObject:path];
//[self parseXMLFileAtURL:path];
caricato = YES;}
Here I call when I use the RefreshControl:
- (void)refreshControlRequest{
NSLog(#"refreshing...");
NSString * path = #"thexmlpath.xml";
[self performSelector:#selector(parseXMLFileAtURL:) withObject:path];}

hope this will help you
- (void)parserDidStartDocument:(NSXMLParser *)parser {
//NSLog(#"found file and started parsing");
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_async(queue, ^{
alertView = [[UIAlertView alloc] initWithTitle:#"Caricamento..."
message:#"\n"
delegate:self
cancelButtonTitle:nil
otherButtonTitles:nil];
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
spinner.center = CGPointMake(139.5, 75.5); // .5 so it doesn't blur
[alertView addSubview:spinner];
[spinner startAnimating];
[alertView show];
});
dispatch_release(queue);
}

Related

NSoperation - string not visible outside the block

I am currently working on a project and using tesseract API .
The code is following :
UIImage *bwImage = [image g8_blackAndWhite];
[self.activityIndicator startAnimating];
// Display the preprocessed image to be recognized in the view
self.imageView.image = bwImage;
G8RecognitionOperation *operation = [[G8RecognitionOperation alloc] init];
operation.tesseract.engineMode = G8OCREngineModeTesseractOnly;
operation.tesseract.pageSegmentationMode = G8PageSegmentationModeAutoOnly;
operation.delegate = self;
operation.recognitionCompleteBlock = ^(G8Tesseract *tesseract) {
// Fetch the recognized text
NSString *recognizedText = tesseract.recognizedText;
NSLog(#"%#", recognizedText);
[self.activityIndicator stopAnimating];
// Spawn an alert with the recognized text
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"OCR Result"
message:recognizedText
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
};
//NSLog(#"%#",);
// Finally, add the recognition operation to the queue
[self.operationQueue addOperation:operation];
}
I want to pass recognizedText string to second View controller but it is not visible outside the block.
How can I achieve this, any advice?
Declare recognizedText outside block with __block keyword to make it visible outside block.
Like below code:
......
__block NSString *recognizedText;//declared outside to make it visible outside block
operation.recognitionCompleteBlock = ^(G8Tesseract *tesseract) {
// Fetch the recognized text
recognizedText = tesseract.recognizedText;
NSLog(#"%#", recognizedText);
[self.activityIndicator stopAnimating];
// Spawn an alert with the recognized text
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"OCR Result"
message:recognizedText
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
};
......

when Navigate the another page Need to add activity indicator

#import "LoginVC.h"
#import "HOMEVC.h"
#import "DashboardVC.h"
#interface LoginVC ()
#end
#implementation LoginVC
UIActivityIndicatorView *spinner ;
-(IBAction)login:(id)sender{
NSString *userUpdate =[NSString stringWithFormat:#"%#",[Usernamefileld text]];
NSString *userUpdate1 =[NSString stringWithFormat:#"%#",[PasswordField text]];
NSString *baseURL = [NSString stringWithFormat:#"http://192.168.1.200:8094/YazakiService.svc/LOGIN/%#/%#",userUpdate,userUpdate1];
NSURL *url = [NSURL URLWithString:[baseURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLResponse *response;
NSError *error;
NSData *responseData =[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSMutableArray *serviceResponse=[NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:&error];
NSLog(#"got response==%#", serviceResponse);
NSDictionary *template=[serviceResponse objectAtIndex:0];
NSString *test=[template objectForKey:#"ValidState"];
// NSString *test1=[template objectForKey:#"Userid"];
NSString *helloString = #"1";
// //
// NSString *helloString1 =#"LFY430";
if ([test isEqual:helloString]) {
[NSThread detachNewThreadSelector:#selector(threadStartAnimating:) toTarget:self withObject:nil];
[self moveToView];
// UIAlertView *alert=[[UIAlertView alloc]initWithTitle:#"Login Successfully" message:#"Correct Uername/Password" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
}
else{
UIAlertView *alert2=[[UIAlertView alloc]initWithTitle:#"Login Failed" message:#"Incorrect Uername/Password" delegate:self cancelButtonTitle:#"Dismiss" otherButtonTitles:nil];
[alert2 show];
[self alertView1:alert2 didDismissWithButtonIndex:alert2];
}
}
- (void)viewDidLoad {
[super viewDidLoad];
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(150, 225, 20, 30)];
[spinner setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleGray];
spinner.color = [UIColor blackColor];
[self.view addSubview:spinner];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
-(void)moveToView{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
DashboardVC *initView = (DashboardVC*)[storyboard instantiateViewControllerWithIdentifier:#"Dashboardvc"];
[initView setModalPresentationStyle:UIModalPresentationFullScreen];
[spinner stopAnimating];
[self presentViewController:initView animated:NO completion:nil];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
[self moveToView];
}
- (void) alertView1:(UIAlertView *)alertView1 didDismissWithButtonIndex:(NSInteger)buttonIndex
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
LoginVC *initView = (LoginVC*)[storyboard instantiateViewControllerWithIdentifier:#"loginvc"];
[initView setModalPresentationStyle:UIModalPresentationFullScreen];
[self presentViewController:initView animated:NO completion:nil];
}
-(void)threadStartAnimating:(id)data
{
[spinner startAnimating];
}
#end
here by i initialse the indicator and start and stop the spinner but its not woking for me...
any one help me to solve the issues how to add the activity indicator when navigation the another view
Thanks in Advance
[self.view addSubview:spinner];
At this line you add the activity indicator to the current ViewController view.
However once you navigate to other view
DashboardVC *initView = (DashboardVC*)[storyboard instantiateViewControllerWithIdentifier:#"Dashboardvc"];
[self presentViewController:initView animated:NO completion:nil];
the current view changes to the new ViewController's view.
The activity indicator isnt present in that view and therefore you wont see your activity indicator there.
To solve, you should again add activity indicator in the second ViewController's viewDidLoad method
In Dashboard VC
- (void)viewDidLoad {
[super viewDidLoad];
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(150, 225, 20, 30)];
[spinner setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleGray];
spinner.color = [UIColor blackColor];
[self.view addSubview:spinner];
}
A better solution would be to use third party progress huds which make
the loading indicator part absolutely easy like MBProgressHUD
You should add activityindicator on navigation controller so, it is remains on front when you navigate.
you should use MBProgressHud the great third party library.
Just put class in your project and import .h file in your class when you want to show activity indicator and then add HUD (activity indicator) like,
[MBProgressHUD showHUDAddedTo:self.view animated:YES];
// in your case show hud on `self.navigationController.view`
// use main thread to show if required
and hide like,
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
// Do something...
dispatch_async(dispatch_get_main_queue(), ^{
[MBProgressHUD hideHUDForView:self.view animated:YES];
});
});
Hope this will help :)
When you stop UIActivityIndicatorView then also hide it.
[spinner setHidesWhenStopped:YES];
EDIT:
If you are not sure about NSThread then just do like this.
if ([test isEqual:helloString]) {
//[NSThread detachNewThreadSelector:#selector(threadStartAnimating:) toTarget:self withObject:nil];
[spinner startAnimating];
[self moveToView];
}
And when you want to stop it ten
[spinner stopAnimating];
[spinner setHidesWhenStopped:YES];
instead of using indicator , use svprogresshud.Check this link https://github.com/SVProgressHUD/SVProgressHUD.
if you want animated progressbar check this link https://github.com/cemolcay/GiFHUD

UIActivityIndicatorView not working right

I have the following initialization in viewDidLoad:
self.indicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
[self.indicator setCenter:CGPointMake([[UIScreen mainScreen]bounds].size.width/2, [[UIScreen mainScreen]bounds].size.height/2)];
//self.indicator.hidden = YES;
[self.indicator setHidesWhenStopped:1];
self.indicator.color = [UIColor orangeColor];
self.indicator.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;
Now if I add the following 2 lines, the indicator shows and spins:
[self.view addSubview:self.indicator];
//self.indicator.hidden = NO;
[self.indicator startAnimating];
Thats not what I want, because the indicator should first show when I call my method, lets call it pressButton. I would then do the following:
- (void)pressButton {
[self.view addSubview:self.indicator];
[self.indicator startAnimating];
dispatch_async(dispatch_get_main_queue(), ^{
WebAccess *web = [WebAccess new];
NSDictionary *dicResults = [web logon:self.email.text :self.password.text];
if([[dicResults valueForKey:#"StatusCode"] intValue] == 200){// ALL IS OK
appDelegate.accessToken = [dicResults valueForKey:#"AccessToken"];
dicResults = [web getAccount:appDelegate.accessToken];
NSLog(#"dicResults after getaccount: %#", dicResults);
if([[dicResults valueForKey:#"StatusCode"] intValue] == 200){//dicResults holds a new object now!
NSArray *usersArray = [dicResults valueForKeyPath:#"Account.Users"];
NSLog(#"usersArray: %#", usersArray);//CORRECT DATA RECEIVED: YES
if(usersArray.count){
[[appDelegate cdh]deleteAllFromEntityWithName:#"AccountData"];
[[appDelegate cdh]deleteAllFromEntityWithName:#"UserData"];//------------- REMOVE ALL WHEN LOADING NEW USER. AMYBE TOO QF. CHECK WITH DESIGNER
}else{
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:#"Error" message:#"No users found on this account!" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alertView show];
}
//more code........
appDelegate.users = [NSMutableArray arrayWithArray:[[appDelegate cdh] fetchUsers]];
if(appDelegate.users.count){
NSArray *currentUserArray = [NSArray arrayWithArray:[[appDelegate cdh]fetchCurrentUser]];
appDelegate.currentUser = [currentUserArray lastObject];
if(appDelegate.currentUser==nil)
appDelegate.currentUser = appDelegate.users[0];
}
[menu goToVC:1];
}
}else if([[dicResults valueForKey:#"StatusCode"] intValue] == 201){
UIAlertView *alertView = [[UIAlertView alloc]initWithTitle:#"Error" message:#"Wrong email or password!" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alertView show];
}
[self.indicator stopAnimating];
});
}
I could've sworn I had it working yesterday when testing, but now it doesn't. Whats weird is if i put those same two lines from my press button method into viewdidload, the indicator shows, but when I do it inside my method (but obv outside the dispatch) it never shows....
Any help appreciated
Spin your long running process off onto its own thread. Leave the main thread open for UI updates.
- (void)pressButton
{
[self.view addSubview:self.indicator];
[self.indicator startAnimating];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Code for your long running process to run in the background...
// Stop your activity indicator back on the main thread
dispatch_async(dispatch_get_main_queue(), ^{
[self.indicator stopAnimating];
});
});
}

How to show alertview indicator before pulling json data( iOS6 )

Could any one please help me with this code i'm trying to call alertview indicator before pulling json data in my iOS app but i don't know how to check if the data already loaded and then disappear the alertview indicator, For now it always appears even all data aleady loaded. here is my code:
//
// Firstcine.m
//
//
//
//
#import "Firstcine.h"
#interface Firstcine (){
UIAlertView *loading;
}
#end
#implementation Firstcine
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Loading Show Alert View...
loading = [[UIAlertView alloc] initWithTitle:#"" message:#"Please Wait..."
delegate:nil cancelButtonTitle:nil otherButtonTitles:nil];
UIActivityIndicatorView *progress= [[UIActivityIndicatorView
alloc] initWithFrame:CGRectMake(125, 50, 30, 30)];
progress.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhiteLarge;
[loading addSubview:progress];
[progress startAnimating];
[loading show];
// dis play all data after first loaded
NSURL *url = [NSURL URLWithString:#"http://localhost/App/first.php"];
NSData *jsonData = [NSData dataWithContentsOfURL:url];
NSArray *json = [NSJSONSerialization JSONObjectWithData:
jsonData options:NSJSONReadingAllowFragments error:nil];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"bg_tile.png"]];
NSDictionary *dict = [json objectAtIndex:0];
name.text = [dict valueForKey:#"name"];
time.text = [dict valueForKey:#"time"];
date.text = [dict valueForKey:#"date"];
price.text = [dict valueForKey:#"price"];
// then display photo
UIImageView *image = [[UIImageView alloc]initWithFrame:CGRectMake(75, 87, 150,200)];
image.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:
[NSURL URLWithString:[dict valueForKey:#"photo" ]]]];
[self.view addSubview:image];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Have you tried something like this
UIAlertView *alertView = [[UIAlertView alloc]
initWithTitle:#"Configuring Preferences\nPlease Wait..."
message:nil
delegate:nil
cancelButtonTitle:nil
otherButtonTitles:nil];
[alertView show];
UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
indicator.center = CGPointMake(alertView.bounds.size.width / 2, alertView.bounds.size.height - 50);
[indicator startAnimating];
[alertView addSubview:indicator];
dispatch_queue_t downloadQueue = dispatch_queue_create("saver", NULL);
dispatch_async(downloadQueue, ^{
// do some heavy lifting ? like a fetch
dispatch_async(dispatch_get_main_queue(), ^{
// hide the view
[alertView dismissWithClickedButtonIndex:0 animated:YES];
});
});

Code in multipeer method called with 20s delay

I am using multipeer connectivity and this is one of the methods:
-(void)session:(MCSession *)session didStartReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID withProgress:(NSProgress *)progress
{
NSLog(#"RECEIVING... %# from peer: %#", progress, peerID);
UIProgressView *progressBar = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleBar];
progressBar.frame = CGRectMake(0, 200, 100, 20);
progressBar.progress = 0.5;
UIButton* btn = [BluetoothDeviceDictionary objectForKey:peerID];
[self.view addSubview:progressBar];
UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:#"Alert View Title" message:#"Alert View Text" delegate:nil cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
[alertView show];
}
For some VERY STRANGE reason, when this method is called, and I know it is called because of the response from the NSLog, the rest of the code is not executed. The alert appears 20 seconds (more or less) after the NSLog has appeared, and the progress view never appears. I can't get why. This happens for most of the methods in multipeer connectivity framework. How is this possible?
EDIT: actually the progress view appears, but much much after the method is called
It's possible that the session delegate's method is being invoked on a background thread. UIKit calls should only be made on the main thread, so you may need to move your code that interacts with UIKit to another method like this:
- (void) updateUI {
UIProgressView *progressBar = [[UIProgressView alloc];
initWithProgressViewStyle:UIProgressViewStyleBar];
progressBar.frame = CGRectMake(0, 200, 100, 20);
progressBar.progress = 0.5;
UIButton* btn = [BluetoothDeviceDictionary objectForKey:peerID];
[self.view addSubview:progressBar];
UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:#"Alert View Title" message:#"Alert View Text" delegate:nil cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
[alertView show];
}
and then call it using:
-(void)session:(MCSession *)session didStartReceivingResourceWithName:(NSString *)resourceName fromPeer:(MCPeerID *)peerID withProgress:(NSProgress *)progress
{
NSLog(#"RECEIVING... %# from peer: %#", progress, peerID);
[self performSelectorOnMainThread:#selector(updateUI) withObject:nil waitUntilDone:YES];
}

Resources