i am using dispatch_async when parsing xml data in a uitable view here is my code:
- (void) Parse{
dispatch_async( dispatch_get_global_queue(0, 0), ^{
NSString *post =[[NSString alloc] initWithFormat:#"http://messages.xml"];
NSData *xmlData=[[NSData alloc]initWithContentsOfURL:[NSURL URLWithString:post]];
xmlParserObject =[[NSXMLParser alloc]initWithData:xmlData];
[xmlParserObject setDelegate:self];
dispatch_async( dispatch_get_main_queue(), ^{
[xmlParserObject parse];
});
});
[messageList reloadData];
}
now uitableview not showing any data in it. it was working perfectly before dispatch_async
I think you have problem in your code. Please reload table data in dispatch_get_main_queue()
- (void) Parse {
dispatch_async( dispatch_get_global_queue(0, 0), ^{
NSString *post =[[NSString alloc] initWithFormat:#"http://messages.xml"];
NSData *xmlData=[[NSData alloc]initWithContentsOfURL:[NSURL URLWithString:post]];
xmlParserObject =[[NSXMLParser alloc]initWithData:xmlData];
[xmlParserObject setDelegate:self];
[xmlParserObject parse];
dispatch_async( dispatch_get_main_queue(), ^{
[messageList reloadData];
});
});
}
Related
All my work is going fine, but There is a little problem in it. I have my NSURLRequest in -(void)viewDidLoad{} and it took some time to fetch data from server. I want it to be done in asynchronous way.
Following is my code please suggest me what should I implement.?
Thanks in advance to all of you. :)
- (void)viewDidLoad {
[super viewDidLoad];
[[self tableView2]setDelegate:self ];
[[self tableView2]setDataSource:self];
array=[[NSMutableArray alloc]init];
NSString *castString = [NSString stringWithFormat:#"https://api.themoviedb.org/3/movie/%#/credits?api_key=c4bd81709e87b12e6c74a08609433c49",movieIDinString];
NSURL *url=[NSURL URLWithString:castString];
NSURLRequest *request=[NSURLRequest requestWithURL:url];
connection=[NSURLConnection connectionWithRequest:request delegate:self];
if (connection)
{
webData= [[NSMutableData alloc]init];
}
try this..
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
//Background Thread
NSString *castString = [NSString stringWithFormat:#"https://api.themoviedb.org/3/movie/%#/credits?api_key=c4bd81709e87b12e6c74a08609433c49",movieIDinString];
NSURL *url=[NSURL URLWithString:castString];
NSURLRequest *request=[NSURLRequest requestWithURL:url];
connection=[NSURLConnection connectionWithRequest:request delegate:self];
if (connection)
{
webData= [[NSMutableData alloc]init];
}
dispatch_async(dispatch_get_main_queue(), ^(void){
//Run UI Updates
// reload table view here
[_activityIndicatorImageView stopAnimating];
});
});
If you are using API, it will take some time, to fetch data from server. At this time, you have to use background thread and show activity indicator in main thread. After getting data from API, you need to change thread to main thread. Please check my below code.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
// background thread
// code for API call
dispatch_async(dispatch_get_main_queue(), ^{
// main thread
});
});
You can use callback method also.
[helperApi instaUserDetails:finderDetailsDataDict andCallback:^(id jsonResponse) {
dispatch_async(dispatch_get_main_queue(), ^{
if ([[jsonResponse objectForKey:#"code"] intValue] == 200) {
userDetailsDict = [jsonResponse objectForKey:#"data"];
mediaArray = [[[[jsonResponse objectForKey:#"data"] objectForKey:#"user"] objectForKey:#"media"] objectForKey:#"nodes"];
}
[activityIndicator stopAnimating];
[self createUI];
});
}];
NSURLConnection is deprecated now. Try to use NSURLSession.
Try AFNeworking. It provides several options for async downloads/uploads, with completions blocks.
i am developing an application and in this app i am loading xml data in a uitableview and that table view call parse method after every 5 secs and reload uitable to load new data. Everything was working fine but app got stuck when parsing starts after 5 sec so i decided to implement dispatch_async in parse method but after that application is crashing like after 5 sec whenever app reload uitable. here is my code.
- (void) Parse{
previusCount = rssOutputData.count;
rssOutputData = [[NSMutableArray alloc]init];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSString *post =[[NSString alloc] initWithFormat:#"https://messages_%#.xml",[[NSUserDefaults standardUserDefaults] stringForKey:#"xmls_id"]];
NSData *xmlData=[[NSData alloc]initWithContentsOfURL:[NSURL URLWithString:post]];
xmlParserObject =[[NSXMLParser alloc]initWithData:xmlData];
[xmlParserObject setDelegate:self];
dispatch_async(dispatch_get_main_queue(), ^{
[xmlParserObject parse];
[messageList reloadData];
if (previusCount != rssOutputData.count) {
NSInteger bottomRow = [rssOutputData count] - 1; // this is your count's array.
if (bottomRow >= 0) {
///////getting to latest msg/////////////
NSIndexPath *indexPathnew = [NSIndexPath indexPathForRow:bottomRow inSection:0];
[self.messageList scrollToRowAtIndexPath:indexPathnew atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
}
});
});
}
Method through which i am sending a message to the xml data file.
- (IBAction)sendClicked:(id)sender {
[messageText resignFirstResponder];
if ( [messageText.text length] > 0 ) {
NSString *rawStr;
if ([[NSUserDefaults standardUserDefaults] integerForKey:#"userType"] == 1) {
rawStr = [NSString stringWithFormat:#"data=%#&user_id=%#&session_id=%#", messageText.text, [[NSUserDefaults standardUserDefaults] stringForKey:#"therapist_id"],[[NSUserDefaults standardUserDefaults] stringForKey:#"xmls_id"]];
} else{//////In case of Patient
rawStr = [NSString stringWithFormat:#"data=%#&user_id=%#&session_id=%#", messageText.text, [[NSUserDefaults standardUserDefaults] stringForKey:#"patient_id"],[[NSUserDefaults standardUserDefaults] stringForKey:#"xmls_id"]];
}
NSData *data = [rawStr dataUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:#"http://do_add_message.php"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:data];
NSURLResponse *response;
NSError *err;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];
NSLog(#"responseData: %#", responseData);
//////////////////////
[self Parse];
}
messageText.text = #"";
}
And the Error which i am getting is:
Print your array. Check it twice. I think you are getting an empty array. Print every object in the console which you get from server and which you parse. So you will get idea.
Update:
Just reload the table data on the main thread and don't parse data on it. like:
dispatch_async(dispatch_get_main_queue(), ^{
[messageList reloadData];
});
Put the other code outside the main thread.
I am having a problem in calling web services when the image are being loaded in the tableView with AsynchImageView files .
Below are the steps of my problem:
I call the web service and when it returns the data i reload the UITableView and load all images with AsynchImageView . The web service returns url of images and some text data .
While the images are being loaded , if I call the same web service again then it runs for 30 seconds and then it times out without returning anything but after that time it works fine whenever I call it .
Here is my code for calling services:
-(void)getUserNotificationsPage:(int)page CallBack:(getNotifications)callback{
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^ {
#try {
getNotificationsArrayResponseCallback=callback;
NSURLRequest * urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#?token=%#&page=%#",GET_USER_NOTIFICATIONS,[[NSUserDefaults standardUserDefaults]objectForKey:#"token"],[NSString stringWithFormat:#"%i",page]]]];
NSError *err;
NSData *returnData = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:nil error:&err];
if(err){
returnData=[NSMutableData data];
}
NSString *returnString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];
dispatch_async(dispatch_get_main_queue(), ^ {
id json = [NSJSONSerialization JSONObjectWithData:returnData options:NSJSONReadingMutableContainers error:nil];
NSArray *returnArray=[json objectForKey:#"notifications"];
getNotificationsArrayResponseCallback(returnArray,YES);
});
}
#catch (NSException *exception) {
dispatch_async(dispatch_get_main_queue(), ^ {
UIAlertView *alert=[[UIAlertView alloc]initWithTitle:LANGUAGE(#"Unknown error occurred") message:nil delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
getNotificationsArrayResponseCallback(nil,NO);
});
}
});
}
If I remove the code where the images are being loaded with asynchImageview then I call call the web service at any time and the response is fast at any time .
AsynchImageView *userProfileImageView =[[AsynchImageView alloc] initWithFrameURLStringAndTag:CGRectMake(5, 215, 70, 70) :[NSString stringWithFormat:#"%#%#",SERVER_URL,"some url" ];
[userProfileImageView setBackgroundColor:[UIColor clearColor]];
[userProfileImageView loadImageFromNetwork];
[cell addSubview:userProfileImageView];
As you can see if I comment the line
[userProfileImageView loadImageFromNetwork];
then I can call the web service any number of times and the response is quick but when the asynchimage view is loading the images and then i call the service then it will time out for that time only . For further calling service works fine .
I think this is the issue with threading or calling serveral url requests at the same time .
is this the class you are using? AsynchImageView
If so, it doesn't actually look like his NSURLConnection is being handled in the background. It looks like it's on the main thread.
I have used this other library in the past with success AsyncImageView
If you look in this other library, they are using a proper dispatch queue for running the background. The other class doesn't have that.
dispatch_async(dispatch_get_main_queue(), ^(void) {
Make custom cell and inside of that cell, put this method
-(void)setImageWithUrl:(NSString *)imageUrl
{
NSURL *urlImage = [NSURL URLWithString:imageUrl];
[self.loadingIndicator startAnimating];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);
dispatch_async(queue, ^{
NSError* error = nil;
NSData *imageData = [NSData dataWithContentsOfURL:urlImage options:nil error:&error];
if(error){
dispatch_sync(dispatch_get_main_queue(), ^{
[self.imgVw setImage:[UIImage imageNamed:#"placeholder.png"]];
[self.loadingIndicator stopAnimating];
[[NSURLCache sharedURLCache] removeAllCachedResponses];
});
}else{
UIImage *image = [UIImage imageWithData:imageData];
dispatch_sync(dispatch_get_main_queue(), ^{
[self.imgVw setImage:image];
[self.loadingIndicator stopAnimating];
[[NSURLCache sharedURLCache] removeAllCachedResponses];
});
}
});
}
Now, call this in cellForRowAtIndexPath method. Put it inside cell nil condition, so that it does not called everytime you scroll.
Make comment in case of any doubt.
if(custCellObj == nil)
{
NSString *imgUrl = [yourArray objectAtIndex:indexPath.row];
[custCellObj setImageWithUrl:imgUrl];
}
I need to load some images from a JSON Object. When these images are loading, I need to show a HUD on my view. I tried to define a HUD like following,
Define HUD in viewDidLoad method
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.mode = MBProgressHUDModeIndeterminate;
hud.labelText = #"Loading Images";
[hud show:YES];
[hud showWhileExecuting:#selector(loadJSONData) onTarget:self withObject:nil animated:YES];
loadJSONData method
-(void)loadJSONData{
_myObject = [[NSMutableArray alloc] init];
NSData *jsonSource = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]];
id jsonObjects = [NSJSONSerialization JSONObjectWithData:
jsonSource options:NSJSONReadingMutableContainers error:nil];
NSArray *dataDic = [jsonObjects objectForKey:#"data"];
for (NSDictionary *dicData in dataDic) {
Lawyer *l = [[Lawyer alloc] init];
dispatch_async(queue, ^{
NSString *imgUrl = [NSString stringWithFormat:#"myurl",l.imageUrl];
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:imgUrl]];
UIImage *image = [UIImage imageWithData:data];
dispatch_async(dispatch_get_main_queue(), ^{
l.uiImage = image;
});
});
[_myObject addObject:[l initFromDictionary:dicData]];
}
}
My out put is showing the HUD for a second and disappeared. No data is loading. How do I fix this.
Thanks in Advance!
Your code is working as expected. loadJSONData performs an asynchronous request so the selector has actually finished executing. What you should do is show the HUD before the method loadJSONData and then hide it when the data has been received in:
dispatch_async(dispatch_get_main_queue(), ^{
l.uiImage = image;
[MBProgressHUD hideHUDForView:self.view animated:YES];
});
Although personally I would have a callback in loadJSONData and perform the HUD dismissal in a completion block.
Use this code :
MBProgressHUD *hud = [[MBProgressHUD alloc] initWithView: self.view];
[self.view addSubview: hud];
hud.labelText = #"Loading Images...";
[hud showAnimated:YES whileExecutingBlock:^{
[self loadJSONData];
} completionBlock:^{
// Refresh UI
}];
But make sure , as whileExecutingBlock using thread you have to make all UI change on main thread.
So I am taking this UIImage data and and converting to a string in base64. the problem is that it hangs on the UI thread whilst converting and I am not sure why.
- (void)processImage:(UIImage*)image{
dispatch_queue_t myQueue = dispatch_queue_create("My Queue",NULL);
[self.spinnerOutlet setAlpha:0.0f];
[self.spinnerOutlet startAnimating];
dispatch_async(myQueue, ^{
// Convert image
NSData *myData = [UIImagePNGRepresentation(image) base64EncodedDataWithOptions:NSDataBase64Encoding64CharacterLineLength];
NSString *myString = [NSString stringWithUTF8String:[myData bytes]];
dispatch_async(dispatch_get_main_queue(), ^{
// Update the UI
[self showSuccessAlertView:#"Success!" message:#"Submitting Image..."];
snapShotInBase64 = myString;
[self sendImagePostRequest];
});
});
}
Try this code:
- (void)processImage:(UIImage*)image{
dispatch_queue_t myQueue = dispatch_queue_create("My Queue",NULL);
[self.spinnerOutlet setAlpha:0.0f];
[self.spinnerOutlet startAnimating];
dispatch_async(myQueue, ^{
// Convert image
NSData *myData = [UIImagePNGRepresentation(image) base64EncodedDataWithOptions:NSDataBase64Encoding64CharacterLineLength];
NSString *myString = [NSString stringWithUTF8String:[myData bytes]];
snapShotInBase64 = myString;
dispatch_async(dispatch_get_main_queue(), ^{
// Update the UI
[self showSuccessAlertView:#"Success!" message:#"Submitting Image..."];
});
});
dispatch_barrier_async(myQueue, ^{
[self sendImagePostRequest];
});
}
or
- (void)processImage:(UIImage*)image{
dispatch_queue_t myQueue = dispatch_queue_create("My Queue",NULL);
[self.spinnerOutlet setAlpha:0.0f];
[self.spinnerOutlet startAnimating];
dispatch_async(myQueue, ^{
// Convert image
NSData *myData = [UIImagePNGRepresentation(image) base64EncodedDataWithOptions:NSDataBase64Encoding64CharacterLineLength];
NSString *myString = [NSString stringWithUTF8String:[myData bytes]];
snapShotInBase64 = myString;
dispatch_async(dispatch_get_main_queue(), ^{
// Update the UI
[self showSuccessAlertView:#"Success!" message:#"Submitting Image..."];
dispatch_async(myQueue, ^{
[self sendImagePostRequest];
});
});
});
}
hope will help. If you upload image in server, why you don`t use AFNetworking library