I want to add activity indicator to image load on image view. How it possible please help, Thank You
My code
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSError *error;
NSLog(#"Error in receiving data %#",error);
NSMutableDictionary *json = [NSJSONSerialization JSONObjectWithData:response options:NSJSONReadingMutableLeaves error:&error];
NSLog(#"response data %#",json);
NSArray* results = [json objectForKey:#"status"];
NSArray *imageUrlArray = [results valueForKey:#"slider_image_path"];
NSLog(#"images %#",imageUrlArray);
NSMutableArray *arrayImages = [[NSMutableArray alloc] init];
for (NSString *strImageUrl in imageUrlArray) {
[arrayImages addObject:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:strImageUrl]]]];
}
self.imageview.animationImages = arrayImages;
_imageview.animationDuration = 10;
_imageview.animationRepeatCount = 0;
[_imageview startAnimating];
}
Do like following :
UIActivityIndicatorView *indctr = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[indctr startAnimating];
[indctr setCenter:self.imageView.center];
[self.contentView addSubview:indctr];
Use this Code
UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[indicator startAnimating];
[indicator setCenter:self.imageView.center];
[self.contentView addSubview:indicator];
Remove the indicator from the superview in the block's succes method.
[_imageView setImageWithURL:[NSURL URLWithString:anURL]
success:^(UIImage *image) {
[indicator removeFromSuperview];
}
failure:^(NSError *error) {
}];
}
You Can use the MBProgress HUD class:https://github.com/jdg/MBProgressHUD
download it and in your code set this:
-(void)viewDidLoad{
MBProgressHUD *HUD = [[MBProgressHUD alloc]initWithView:self.view];
[self.view addSubview:HUD];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSError *error;
NSLog(#"Error in receiving data %#",error);
[HUD show: YES];
NSMutableDictionary *json = [NSJSONSerialization JSONObjectWithData:response options:NSJSONReadingMutableLeaves error:&error];
NSLog(#"response data %#",json);
NSArray* results = [json objectForKey:#"status"];
NSArray *imageUrlArray = [results valueForKey:#"slider_image_path"];
NSLog(#"images %#",imageUrlArray);
NSMutableArray *arrayImages = [[NSMutableArray alloc] init];
for (NSString *strImageUrl in imageUrlArray) {
[arrayImages addObject:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:strImageUrl]]]];
}
self.imageview.animationImages = arrayImages;
_imageview.animationDuration = 10;
_imageview.animationRepeatCount = 0;
[_imageview startAnimating];
[HUD hide: YES];
}
Related
I have one login screen after that it will move to next view controller which have i have used some networks like http,json to get data from server. when i enter login username/password then if i click login button its getting delay to 8 seconds after that only it moving to next view controller.Still that my login screen alone showing for 8 seconds and then only it move to next view controller.
Here my login controller.m:
#implementation mainViewController
- (void)viewDidLoad {
[super viewDidLoad];
_username.delegate = self;
_password.delegate = self;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (![defaults boolForKey:#"reg"]) {
NSLog(#"no user reg");
_logBtn.hidden = NO;
}
}
- (void)viewWillAppear:(BOOL)animated
{
[self.navigationController setNavigationBarHidden:YES animated:animated];
[super viewWillAppear:animated];
_username.text = nil;
_password.text = nil;
}
- (IBAction)LoginUser:(id)sender {
if ([_username.text isEqualToString:#"sat"] && [_password.text isEqualToString:#"123"]) {
NSLog(#"Login success");
[self performSegueWithIdentifier:#"nextscreen" sender:self];
}
else {
NSLog(#"login was unsucess");
// Alert message
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:#"wrong"
message:#"Message"
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *actionOk = [UIAlertAction actionWithTitle:#"Ok"
style:UIAlertActionStyleDefault
handler:nil];
[alertController addAction:actionOk];
[self presentViewController:alertController animated:YES completion:nil];
}
}
Here my nextcontroller.m
- (void)viewDidLoad {
[super viewDidLoad];
//for search label data
self.dataSourceForSearchResult = [NSArray new];
//collection of array to store value
titleArray = [NSMutableArray array];
// here only i am getting data from server
[self getdata];
self.collectionView.dataSource = self;
self.collectionView.delegate = self;
[self.collectionView reloadData];
}
Help me out. If my question din't understand.I can tell more about my post. And in my nextcontroller.m [self getdata] is i am getting data from server url.Thanks
My get data:
-(void)getdata {
NSString *userName = #“users”;
NSString *password = #“images”;
NSData *plainData = [password dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64String = [plainData base64EncodedStringWithOptions:0];
base64String=[self sha256HashFor: base64String];
NSString *urlString = #"https://porterblog/image/file”;
NSMutableURLRequest *request= [[NSMutableURLRequest alloc] init];
[request setURL:[NSURL URLWithString:urlString]];
[request setHTTPMethod:#"GET"];
NSString *authStr = [NSString stringWithFormat:#"%#:%#", userName, base64String];
NSData *authData = [authStr dataUsingEncoding:NSUTF8StringEncoding];
NSString *authValue = [NSString stringWithFormat:#"Basic %#", [authData base64EncodedStringWithOptions:0]];
[request setValue:authValue forHTTPHeaderField:#"Authorization"];
NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *str = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];
NSError * error;
self->arrayPDFName = [[NSMutableArray alloc]init];
NSDictionary *jsonResults = [NSJSONSerialization JSONObjectWithData:returnData options:NSJSONReadingMutableContainers error:nil];
NSDictionary *dictOriginal = jsonResults[#“birds”];
[titleArray addObject:[NSString stringWithFormat:#" birds(%#)”, dictOriginal[#"count"]]];
NSDictionary *dictOriginal2 = jsonResults[#"owl”];
[titleArray addObject:[NSString stringWithFormat:#" Owl(%#)”, dictOriginal2[#"count"]]];
NSDictionary *dictOriginal3 = jsonResults[#"pensq”];
[titleArray addObject:[NSString stringWithFormat:#" Pensq(%#)”, dictOriginal3[#"count"]]];
NSDictionary *dictOriginal4 = jsonResults[#“lion”];
[titleArray addObject:[NSString stringWithFormat:#" lion(%#)”, dictOriginal4[#"count"]]];
NSArray *arrayFiles = [NSArray arrayWithObjects: dictOriginal, dictOriginal2, dictOriginal3, dictOriginal4, nil];
NSLog(#"str: %#", titleArray);
for (NSDictionary *dict in arrayFiles) {
NSMutableArray *arr = [NSMutableArray array];
NSArray *a = dict[#"files"];
for(int i=0; i < a.count; i ++) {
NSString *strName = [NSString stringWithFormat:#"%#",[[dict[#"files"] objectAtIndex:i] valueForKey:#"name"]];
[arr addObject:strName];
}
[arrayPDFName addObject:arr];
}
NSString *errorDesc;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory1 = [paths objectAtIndex:0];
NSString *plistPath = [documentsDirectory1 stringByAppendingPathComponent:#"SampleData.plist"];
NSString *error1;
returnData = [ NSPropertyListSerialization dataWithPropertyList:jsonResults format:NSPropertyListXMLFormat_v1_0 options:0 error:&error];
if(returnData ) {
if ([returnData writeToFile:plistPath atomically:YES]) {
NSLog(#"Data successfully saved.");
}else {
NSLog(#"Did not managed to save NSData.");
}
}
else {
NSLog(#"%#",errorDesc);
}
NSDictionary *stringsDictionary = [NSDictionary dictionaryWithContentsOfFile:plistPath];
}
EDITED:
`- (void)viewDidLoad {
[super viewDidLoad];
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
self.dataSourceForSearchResult = [NSArray new];
titleArray = [NSMutableArray array];
//Background Tasks
[self getdata];
dispatch_async(dispatch_get_main_queue(), ^(void){
//Run UI Updates
self.collectionView.dataSource = self;
self.collectionView.delegate = self;
[self.collectionView reloadData];
self.navigationItem.hidesBackButton = YES;
});
});
}`
You're getting your data using main thread you need do to that in background then invoke the code you need (as i see is reload collectionView)
I assume that because you didn't show the getdata method code
If that the case you can use this code:
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
//Background Tasks
[self getdata];
dispatch_async(dispatch_get_main_queue(), ^(void){
//Run UI Updates
[self.collectionView reloadData];
});
});
It's mean that your VC will show immediately but the collectionView fill after you finish load the data, you can put some old data while loading like Facebook app (you see latest retrieved posts until finish loading].
Edit:
In your code you replace viewdidload method in nextController with next code:
- (void)viewDidLoad {
[super viewDidLoad];
//for search label data
self.dataSourceForSearchResult = [NSArray new];
//collection of array to store value
titleArray = [NSMutableArray array];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
//Background Tasks
[self getdata];
dispatch_async(dispatch_get_main_queue(), ^(void){
//Run UI Updates
[self.collectionView reloadData];
});
});
self.collectionView.dataSource = self;
self.collectionView.delegate = self;
}
I am working in AVAudioplayer in iOS. I am displaying an activity indicator for loading time if a user clicks the play button. My problem is that when I click the play button the loading time activity indicator is not displayed.
-(void)loadData
{
url=[NSURL URLWithString:#"http://www.urls.com"];
NSMutableURLRequest *request=[[NSMutableURLRequest alloc]initWithURL:url];
[[NSURLConnection alloc]initWithRequest:request delegate:self];
[UIApplication sharedApplication].networkActivityIndicatorVisible=YES;
[self.view addSubview:loadingView];
[activityView startAnimating];
loadingConnection=[[NSURLConnection alloc]initWithRequest:request delegate:self startImmediately:YES];
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
responseData=[[NSMutableData alloc]init];
[responseData setLength:0];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
if(connection==loadingConnection)
{
[responseData appendData:data];
}
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[UIApplication sharedApplication].networkActivityIndicatorVisible=NO;
[activityView stopAnimating];
[loadingView removeFromSuperview];
if(connection==loadingConnection)
{
NSError *jsonError = nil;
id jsonObject = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&jsonError];
if ([jsonObject isKindOfClass:[NSArray class]])
{
//NSArray *jsonArray = (NSArray *)jsonObject;
}
else if ([jsonObject isKindOfClass:[NSDictionary class]])
{
NSDictionary *jsonDictionary = (NSDictionary *)jsonObject;
NSArray *array=[[NSArray alloc]init];
array=[jsonDictionary objectForKey:#"audio-urls"];
dataDictionary=[array objectAtIndex:0];
NSLog(#"%#",dataDictionary);
}
[urlsArray addObject:[dataDictionary objectForKey:#“Audio1”]];
[urlsArray addObject:[dataDictionary objectForKey:#“Audio2”]];
[urlsArray addObject:[dataDictionary objectForKey:#“Audio3”]];
[urlsArray addObject:[dataDictionary objectForKey:#“Audio4”]];
[urlsArray addObject:[dataDictionary objectForKey:#“Audio5”]];
[urlsArray addObject:[dataDictionary objectForKey:#“Audio6”]];
NSLog(#"%#",urlsArray);
}
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
[UIApplication sharedApplication].networkActivityIndicatorVisible=NO;
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"No Internet Connection" message:#"Please ensure you have internet connection" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
[activityView stopAnimating];
[loadingView removeFromSuperview];
}
- (void)viewDidLoad
{
playing=NO;
[self loadData];
// [self temp];
[self performSelector:#selector(loadData) withObject:nil afterDelay:3.0f];
urlsArray=[[NSMutableArray alloc]init];
[super viewDidLoad];
}
-(void)temp
{
// loading View
loadingView=[[UILabel alloc]initWithFrame:CGRectMake(135, 200, 40, 40)];
loadingView.backgroundColor=[UIColor clearColor];
loadingView.clipsToBounds=YES;
loadingView.layer.cornerRadius=10.0;
activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
activityView.frame = CGRectMake(10, 11, activityView.bounds.size.width, activityView.bounds.size.height);
[loadingView addSubview:activityView];
}
-(void)playOrPauseButtonPressed:(id)sender
{
if(playing==NO)
{
[self temp];
// [self.view addSubview:loadingView];
// [loadingView addSubview:activityView];
// [UIApplication sharedApplication].networkActivityIndicatorVisible=YES;
[playButton setBackgroundImage:[UIImage imageNamed:#"Pause.png"] forState:UIControlStateNormal];
// Here Pause.png is a image showing Pause Button.
NSError *err=nil;
AVAudioSession *audioSession=[AVAudioSession sharedInstance];
[audioSession setCategory:AVAudioSessionCategoryPlayback error:nil];
NSLog(#"%# %d",urlsArray,selectedIndex);
NSString *sourcePath=[urlsArray objectAtIndex:selectedIndex];
NSData *objectData=[NSData dataWithContentsOfURL:[NSURL URLWithString:sourcePath]];
NSLog(#"%#",objectData);
audioPlayer = [[AVAudioPlayer alloc] initWithData:objectData error:&err];
if(err)
{
NSLog(#"Error %ld,%#",(long)err.code,err.localizedDescription);
}
NSTimeInterval bufferDuration=0.005;
[audioSession setPreferredIOBufferDuration:bufferDuration error:&err];
if(err)
{
NSLog(#"Error %ld, %#", (long)err.code, err.localizedDescription);
}
double sampleRate = 44100.0;
[audioSession setPreferredSampleRate:sampleRate error:&err];
if(err)
{
NSLog(#"Error %ld, %#",(long)err.code,err.localizedDescription);
}
[audioSession setActive:YES error:&err];
if(err)
{
NSLog(#"Error %ld,%#", (long)err.code, err.localizedDescription);
}
sampRate=audioSession.sampleRate;
bufferDuration=audioSession.IOBufferDuration;
NSLog(#"SampeRate:%0.0fHZI/OBufferDuration:%f",sampleRate,bufferDuration);
audioPlayer.numberOfLoops = 0;
[audioPlayer prepareToPlay];
[audioPlayer play];
audioPlayer.delegate=self;
if(!audioPlayer.playing)
{
[audioPlayer play];
}
playing=YES;
}
else if (playing==YES)
{
[playButton setBackgroundImage:[UIImage imageNamed:#"play.png"] forState:UIControlStateNormal];
[audioPlayer pause];
playing=NO;
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(updateViewForPlayerState) userInfo:nil repeats:YES];
}
if (self.audioPlayer)
{
[self updateViewForPlayerInfo];
[self updateViewForPlayerState];
[self.audioPlayer setDelegate:self];
}
}
//Create and add the Activity Indicator to view
UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
activityIndicator.alpha = 1.0;
activityIndicator.center = CGPointMake(160, 360);
activityIndicator.hidesWhenStopped = NO;
[self.view addSubview:activityIndicator];
[activityIndicator startAnimating];`
Have a nice day!
no need to NSURLConnection delegate method
direct pass url in AVAudioPlayer
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
[spinner setCenter:CGPointMake(230, 330)]; // I do this because I'm in landscape mode
[yourview addSubview:spinner];
[spinner setColor:[UIColor whiteColor]];
[spinner startAnimating];
[self performSelector:#selector(download) withObject:nil afterDelay:0.50f];
-(void)download
{
NSData *audioData = [NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://www.dailywav.com/0813/bicycles.wav"]];
NSString *docDirPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#/bicycles.wav", docDirPath ];
[audioData writeToFile:filePath atomically:YES];
NSError *error;
NSURL *fileURL = [NSURL fileURLWithPath:filePath];
AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:&error];
if (player == nil) {
NSLog(#"AudioPlayer did not load properly: %#", [error description]);
} else {
[spinner stopAnimating
];
[player play];
}
}
I have a view controller, that loads some an array. While everything is loading, I need to present another view controller (with the UIProgressView) and update it's UI (the progress property of a UIProgressView) and then dismiss and present first vc with downloaded data. I'm really struggling on it and I've tried delegation, but nothing worked for me.
- (void)viewDidLoad
{
[super viewDidLoad];
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"downloaded"]) {
} else {
NSLog(#"First time Launched");
ProgressIndicatorViewController *progressVC = [ProgressIndicatorViewController new];
progressVC.modalPresentationStyle = UIModalPresentationFullScreen;
[self syncContacts];
[self presentViewController:progressVC animated:YES completion:nil];
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:#"downloaded"];
[progressVC release];
}
}
sync contacts method:
- (void)syncContacts
{
NSLog(#"Sync data");
NSMutableArray *allContacts = [ContactsOperations getAllContactsFromAddressBook];
NSInteger allContactsCount = [allContacts count];
if (allContactsCount > 0) {
for (ContactData *contact in allContacts) {
NSMutableArray *phoneNumbersArray = [[NSMutableArray alloc] init];
NSString *nospacestring = nil;
for (UserTelephone *tel in [contact.abonNumbers retain]) {
NSArray *words = [tel.phoneNumber componentsSeparatedByCharactersInSet :[NSCharacterSet whitespaceCharacterSet]];
NSString *nospacestring = [words componentsJoinedByString:#""];
[phoneNumbersArray addObject:nospacestring];
}
contact.abonNumbers = phoneNumbersArray;
if (phoneNumbersArray != nil) {
NSLog(#"NOT NULL PHONENUMBERS: %#", phoneNumbersArray);
}
NSDictionary *dataDictionary = [[NSDictionary alloc] initWithObjectsAndKeys:contact.abonNumbers, #"phoneNumbers", contact.contactName, #"fullName", [NSNumber numberWithBool:contact.isBlackList], #"blacklist", [NSNumber numberWithBool:contact.isIgnore], #"ignore", contact.status, #"status", nil];
NSLog(#"dictionary: %#", dataDictionary);
NSError *error;
NSData *postData = [NSJSONSerialization dataWithJSONObject:dataDictionary options:0 error:&error];
NSLog(#"POST DATA IS : %#", postData);
NSMutableURLRequest *newRequest = [self generateRequest:[[NSString stringWithFormat:#"%#c/contacts%#%#", AVATATOR_ADDR, SESSION_PART, [[ServiceWorker sharedInstance] SessionID]] stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding] withHTTPMethod:#"POST"];
[newRequest setHTTPBody:postData];
[newRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
//__block NSMutableData *newData;
[NSURLConnection sendAsynchronousRequest:newRequest queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError)
{
if (!connectionError) {
NSDictionary *allData = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(#"alldata from contacts: %#", allData);
//NSInteger errorCode = [[allData objectForKey:#"CommandRes"] integerValue];
//if (errorCode == 0) {
NSInteger remoteId = [[allData objectForKey:#"contactId"] integerValue];
contact.remoteId = remoteId;
NSLog(#"remote id is from parse content : %d", remoteId);
[[AvatatorDBManager getSharedDBManager]createContactWithContactData:contact];
} else {
NSLog(#"error");
}
}];
//Somewhere here I need to update the UI in another VC
[phoneNumbersArray release];
[dataDictionary release];
}
} else {
}
}
generate request method:
- (NSMutableURLRequest *)generateRequest:(NSString *)urlString withHTTPMethod:(NSString *)httpMethod
{
NSLog(#"url is :%#", urlString);
NSURL *url = [NSURL URLWithString:urlString];
request = [NSMutableURLRequest requestWithURL:url];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
[request setHTTPMethod:httpMethod];
return request;
}
ProgressViewController is just an empty VC with the progress bar. No code yet.
In the view controller that will display the progress view expose a method like this...
- (void)updateProgress:(float)progress;
Its implementation will look like this...
- (void)updateProgress:(float)progress {
[self.progressView setProgress:progress animated:YES];
}
On the main view controller you need to execute the long-running process on a background thread. Here's viewDidLoad for the main view controller. This example code uses a property for the progress view controller (you may not require this) and assumes your are in a navigation controller...
- (void)viewDidLoad {
[super viewDidLoad];
// Create and push the progress view controller...
self.pvc = [[ProgressViewController alloc] init];
[self.navigationController pushViewController:self.pvc animated:YES];
// Your long-running process executes on a background thread...
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Your long-running process goes here. Wherever required you would
// call updateProgress but that needs to happen on the main queue...
dispatch_async(dispatch_get_main_queue(), ^{
[self.pvc updateProgress:progress];
});
// At the end pop the progress view controller...
dispatch_async(dispatch_get_main_queue(), ^{
[self.navigationController popViewControllerAnimated:YES];
});
});
}
- (void) setRooms:(NSArray *)newRooms
{
NSLog(#"Main thread(cp3)... %d", [rooms count]);
rooms = newRooms;
[table reloadData];
NSLog(#"Main thread(cp4)... %d", [rooms count]);
}
- (void) parseJSONWithURL:(NSURL *)jsonURL
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSLog(#"Main thread(cp1)...%d", [rooms count]);
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{
NSLog(#"Background thread(cp1)...%d", [rooms count]);
NSError *error = nil;
// Request the data and store in a string.
NSString *resp = [NSString stringWithContentsOfURL:jsonURL
encoding:NSASCIIStringEncoding
error:&error];
// Convert the String into an NSData object.
NSData *data = [resp dataUsingEncoding:NSASCIIStringEncoding];
// Parse that data object using NSJSONSerialization without options.
NSDictionary *json = [[NSDictionary alloc] init];
json = [NSJSONSerialization JSONObjectWithData:data
options:kNilOptions
error:&error];
// Return to the main thread to update the UI elements
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(#"Main thread(cp2)...%d", [rooms count]);
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
[self setRooms:[json valueForKey:#"Rooms"]];
});
NSLog(#"Background thread(cp2)...%d", [rooms count]);
});
NSLog(#"Main thread(cp5)...%d", [rooms count]);
}
Try this
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{
NSError *error = nil;
// Request the data and store in a string.
NSString *resp = [NSString stringWithContentsOfURL:jsonURL
encoding:NSASCIIStringEncoding
error:&error];
if (error == nil) {
// Convert the String into an NSData object.
NSData *data = [resp dataUsingEncoding:NSASCIIStringEncoding];
// Parse that data object using NSJSONSerialization without options.
NSDictionary *json = [[NSDictionary alloc] init];
json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
dispatch_sync(dispatch_get_main_queue(), ^{
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
_rooms = [json valueForKey:#"Rooms"];
[_table reloadData];
});
}
});
or try
[self performSelectorOnMainThread:#selector(udpateAfterFetch:) withObject: [json valueForKey:#"Rooms"] waitUntilDone:YES];
-(void)udpateAfterFetch:(NSArray or whatever *) yourObject
{
_rooms = yourObject;
[_table reloadData];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
The table is not being reloaded because any UI update should happen in the main thread and it is not happening so in ur lines of code.
I've used dispatch_async to put in background a xml document's parsing, I've putted information in an array and, with a for cycle, I would assign the content of every element to an UILabel (for now), the problem is that in the output console I can see the right content of every element but the uilabel are added only in the end after a long delay.
Code:
#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_async(kBgQueue, ^{
NSData *xmlData = [[NSMutableData alloc] initWithContentsOfURL:url];
NSError *error;
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:xmlData options:0 error:&error];
NSArray *areaCortina = [doc nodesForXPath:#"query" error:nil];
int i=0;
for (GDataXMLElement *element in areaCortina) {
NSLog(#"%#",[[element attributeForName:#"LiftName"] stringValue]); //data are shown correctly
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, (30+10)*i, 200, 30)];// don't appear after log
[label setText:[[element attributeForName:#"name"] stringValue]];
[self.view performSelectorOnMainThread:#selector(addSubview:) withObject:label waitUntilDone:YES];
i++;
}
As you can see i've used performSelectorOnMainThread but nothig, the label doesn't appear once at once but are shown correctly only after a 10 or 15 seconds after the end of the block.
Ideas?
Thanks in advance
Ok edit 1
Thanks to the advice of Shimanski Artem I've now the following:
#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
...
dispatch_async(kBgQueue, ^{
NSData *xmlData = [[NSMutableData alloc] initWithContentsOfURL:url];
NSError *error;
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:xmlData options:0 error:&error];
NSArray *areaCortina = [doc nodesForXPath:#"query" error:nil];
self.data = [[NSMutableArray alloc] init];
for (GDataXMLElement *element in areaCortina) {
[self.data addObject:[[element attributeForName:#"name"] stringValue]];
}
[[NSNotificationCenter defaultCenter] postNotificationName:#"name" object:self];
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(caricaItem) name:#"name" object:nil];
...
} //end method
-(void) caricaItem
{
int i=0;
for (NSString * string in self.dati) {
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, (30+10)*i, 200, 30)];
[label setText:string];
[self.view addSubview:label];
i++;
}
}
I've put uilabels creation out of dispatch, in the caricaItem method where i've ready an array full of precious data, but same delay... and the same if in caricaItem i use a UITableView...
What is the right way to proceed?
Thanks