NSXMLParser 工作正常,但如何实现 UIActivityIndicator 来显示网络活动?
我从 NSXMLParser 将数据加载到 UITableView 中。 这一切都工作正常,但我想要实现的是应用程序加载 XML 数据时缺少一些活动,因此这对用户来说更加友好。 我发现的一些示例仍然让我感到困惑,因为我没有像大多数人那样遵循 XMLParser 实现的相同方式。
我在这里提供我的数据,请提供一些代码示例,说明我应该如何将其放入我的代码中。
XMLParser.h:
#import <UIKit/UIKit.h>
@class DAFAppDelegate, Stage, Month;
@interface XMLParser : NSObject <NSXMLParserDelegate>
{
NSMutableString *currentElementValue;
DAFAppDelegate *appDelegate;
Stage *aStage;
Month *aMonth;
}
- (XMLParser *) initXMLParser;
+ (NSDate *)dateFromString:(NSString *)dateString;
+ (NSString *)stringFromDate:(NSDate *)stringDate;
@end
XMLParser.m:
#import "XMLParser.h"
#import "DAFAppDelegate.h"
#import "Stage.h"
#import "Month.h"
@implementation XMLParser
- (XMLParser *) initXMLParser
{
[super init];
appDelegate = (DAFAppDelegate *)[[UIApplication sharedApplication] delegate];
return self;
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
{
if([elementName isEqualToString:@"Stages"])
{
//Initialize the array.
appDelegate.stages = [[NSMutableArray alloc] init];
}
if([elementName isEqualToString:@"Month"])
{
//Initialize the Month.
aMonth = [[Month alloc] init];
aMonth.stagesPerMonth = [[NSMutableArray alloc] init];
//Extract the attribute here.
aMonth.name = [attributeDict valueForKey:@"name"];
aMonth.monthID = [[attributeDict objectForKey:@"id"] integerValue];
NSLog(@"Reading Month id value :%i", aMonth.monthID);
NSLog(@"Reading Month name value :%@", aMonth.name);
}
if([elementName isEqualToString:@"Stage"])
{
//Initialize the Stage.
aStage = [[Stage alloc] init];
//Extract the attribute here.
aStage.stageID = [[attributeDict objectForKey:@"id"] integerValue];
NSLog(@"Reading id value :%i", aStage.stageID);
}
NSLog(@"Processing Element: %@", elementName);
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if(!currentElementValue)
{
currentElementValue = [[NSMutableString alloc] initWithString:string];
}
else
{
[currentElementValue appendString:string];
}
NSLog(@"Processing Value: %@", currentElementValue);
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
NSDate* date = [NSDate date];
NSDateFormatter* nsformatter = [[[NSDateFormatter alloc] init] autorelease];
[nsformatter setDateFormat:@"yyyy-MM-dd"];
NSDate* stageDate = [XMLParser dateFromString:aStage.end];
if([elementName isEqualToString:@"Stages"])
{
return;
}
if([elementName isEqualToString:@"Month"])
{
if (!aMonth.stagesPerMonth || aMonth.stagesPerMonth.count)
{
[appDelegate.stages addObject:aMonth];
}
[aMonth release];
aMonth = nil;
}
if([elementName isEqualToString:@"Stage"])
{
NSTimeInterval interval = [date timeIntervalSinceDate:stageDate];
if (interval < 0)
{
[aMonth.stagesPerMonth addObject:aStage];
}
[aStage release];
aStage = nil;
}
else
{
[aStage setValue:currentElementValue forKey:elementName];
[currentElementValue release];
currentElementValue = nil;
}
}
-(void) parserDidStartDocument:(NSXMLParser *)parser
{
NSLog(@"parserDidStartDocument");
}
-(void) parserDidEndDocument: (NSXMLParser *)parser
{
NSLog(@"parserDidEndDocument");
}
+ (NSDate *)dateFromString:(NSString *)dateString
{
NSDateFormatter *nsDateFormatter = [[NSDateFormatter alloc] init];
[nsDateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm"];
NSDate *date = [nsDateFormatter dateFromString:dateString];
return date;
[nsDateFormatter release];
}
+ (NSString *)stringFromDate:(NSDate *)stringDate
{
NSDateFormatter *stringDateFormatter = [[NSDateFormatter alloc] init];
NSLocale *nlLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"nl_NL"];
[stringDateFormatter setLocale:nlLocale];
[stringDateFormatter setDateFormat:@"EEE', 'dd MMMM yyyy HH:mma"];
NSString *dateString = [stringDateFormatter stringFromDate:stringDate];
return dateString;
[stringDateFormatter release];
}
- (void) dealloc
{
[aStage release];
[aMonth release];
[currentElementValue release];
[super dealloc];
}
@end
DAFAppDelegate.h:
@class RootViewController;
@interface DAFAppDelegate : NSObject <UIApplicationDelegate>
{
UIWindow *window;
UINavigationController *navigationController;
IBOutlet UITabBarController *rootTabController;
RootViewController *rootViewController;
NSMutableArray *stages;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UITabBarController *rootTabController;
@property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
@property (nonatomic, retain) IBOutlet RootViewController *rootViewController;
@property (nonatomic, retain) NSMutableArray *stages;
+ (void) showAlert;
@end
DAFAppDelegate.m:
#import "DAFAppDelegate.h"
#import "RootViewController.h"
#import "XMLParser.h"
@implementation DAFAppDelegate
@synthesize window;
@synthesize navigationController;
@synthesize rootViewController;
@synthesize rootTabController;
@synthesize stages;
+ (void) showAlert
{
UIAlertView *av = [[[UIAlertView alloc] initWithTitle:@"No Connection" message:@"Could not retrieve data" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] autorelease];
[av show];
}
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
NSURL *url = [[NSURL alloc] initWithString:@"http://web.me.com/ijar/Stages.xml"];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
//Initialize the delegate.
XMLParser *parser = [[XMLParser alloc] initXMLParser];
//Set delegate
[xmlParser setDelegate:parser];
//Start parsing the XML file.
BOOL success = [xmlParser parse];
if(success)
{
NSLog(@"No Errors");
}
else
{
[DAFAppDelegate showAlert];
NSLog(@"Error Error Error!!!");
}
[window addSubview:[rootTabController view]];
[window makeKeyAndVisible];
}
- (void)dealloc
{
[navigationController release];
[rootViewController release];
[rootTabController release];
[window release];
[stages release];
[super dealloc];
}
@end
RootViewController.h:
@class DAFAppDelegate;
@interface RootViewController : UITableViewController
{
DAFAppDelegate *appDelegate;
}
@end
RootViewController.m:
#import "RootViewController.h"
#import "DAFAppDelegate.h"
#import "DetailViewController.h"
#import "XMLParser.h"
#import "Stage.h"
#import "Month.h"
#import "AgendaCustomCell.h"
@implementation RootViewController
#pragma mark -
#pragma mark View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
appDelegate = (DAFAppDelegate *)[[UIApplication sharedApplication] delegate];
self.title = NSLocalizedString(@"Agenda", @"Master view navigation title");
UIImageView *image=[[UIImageView alloc]initWithFrame:CGRectMake(0,0,45,45)] ;
[image setImage:[UIImage imageNamed:@"topBarIcon.png"]];
[self.navigationController.navigationBar.topItem setTitleView:image];
self.tableView.backgroundColor = [UIColor clearColor];
}
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [appDelegate.stages count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
Month *aMonth = [appDelegate.stages objectAtIndex:section];
return aMonth.name;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
Month *aMonth = [appDelegate.stages objectAtIndex:section];
return [aMonth.stagesPerMonth count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"AgendaCustomCell";
AgendaCustomCell *cell = (AgendaCustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
NSArray *topLevelObject = [[NSBundle mainBundle] loadNibNamed:@"AgendaCustomCell" owner:nil options:nil];
for (id currentObject in topLevelObject)
{
if ([currentObject isKindOfClass:[UITableViewCell class]])
{
cell = (AgendaCustomCell *)currentObject;
break;
}
}
}
Month *aMonth = [appDelegate.stages objectAtIndex:indexPath.section];
Stage *aStage = [aMonth.stagesPerMonth objectAtIndex:indexPath.row];
NSString *startDate = [XMLParser stringFromDate:[XMLParser dateFromString:aStage.start]];
NSString *endDate = [XMLParser stringFromDate:[XMLParser dateFromString:aStage.end]];
int endDateLength = endDate.length;
NSString *dateTitle = [NSString stringWithFormat:@"%@ - %@", startDate, [endDate substringFromIndex:endDateLength -7]];
cell.titleLabel.text = aStage.title;
cell.dateLabel.text = dateTitle;
cell.nameLabel.text = aStage.teacher;
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 60;
}
#pragma mark -
#pragma mark Table view selection
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//When a row is selected, create the detail view controller and set its detail item to the item associated with the selected row.
DetailViewController *detailViewController = [[DetailViewController alloc] initWithStyle:UITableViewStyleGrouped];
Month *aMonth = [appDelegate.stages objectAtIndex:indexPath.section];
detailViewController.stage = [aMonth.stagesPerMonth objectAtIndex:indexPath.row];
// Push the detail view controller.
[[self navigationController] pushViewController:detailViewController animated:YES];
[detailViewController release];
}
#pragma mark -
#pragma mark Memory management
- (void)dealloc
{
[appDelegate release];
[super dealloc];
}
@end
I load data into my UITableView from an NSXMLParser.
This all works fine but what I would like to implement is some short of activity when the App is loading the XML data, so it all is a bit more friendly for the users.
Some samples I have found still confuse me simply because I did not follow the same way of XMLParser implementation as most same do.
I provide my data here, please give some code samples on how I should put it in my code.
XMLParser.h:
#import <UIKit/UIKit.h>
@class DAFAppDelegate, Stage, Month;
@interface XMLParser : NSObject <NSXMLParserDelegate>
{
NSMutableString *currentElementValue;
DAFAppDelegate *appDelegate;
Stage *aStage;
Month *aMonth;
}
- (XMLParser *) initXMLParser;
+ (NSDate *)dateFromString:(NSString *)dateString;
+ (NSString *)stringFromDate:(NSDate *)stringDate;
@end
XMLParser.m:
#import "XMLParser.h"
#import "DAFAppDelegate.h"
#import "Stage.h"
#import "Month.h"
@implementation XMLParser
- (XMLParser *) initXMLParser
{
[super init];
appDelegate = (DAFAppDelegate *)[[UIApplication sharedApplication] delegate];
return self;
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict
{
if([elementName isEqualToString:@"Stages"])
{
//Initialize the array.
appDelegate.stages = [[NSMutableArray alloc] init];
}
if([elementName isEqualToString:@"Month"])
{
//Initialize the Month.
aMonth = [[Month alloc] init];
aMonth.stagesPerMonth = [[NSMutableArray alloc] init];
//Extract the attribute here.
aMonth.name = [attributeDict valueForKey:@"name"];
aMonth.monthID = [[attributeDict objectForKey:@"id"] integerValue];
NSLog(@"Reading Month id value :%i", aMonth.monthID);
NSLog(@"Reading Month name value :%@", aMonth.name);
}
if([elementName isEqualToString:@"Stage"])
{
//Initialize the Stage.
aStage = [[Stage alloc] init];
//Extract the attribute here.
aStage.stageID = [[attributeDict objectForKey:@"id"] integerValue];
NSLog(@"Reading id value :%i", aStage.stageID);
}
NSLog(@"Processing Element: %@", elementName);
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if(!currentElementValue)
{
currentElementValue = [[NSMutableString alloc] initWithString:string];
}
else
{
[currentElementValue appendString:string];
}
NSLog(@"Processing Value: %@", currentElementValue);
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
{
NSDate* date = [NSDate date];
NSDateFormatter* nsformatter = [[[NSDateFormatter alloc] init] autorelease];
[nsformatter setDateFormat:@"yyyy-MM-dd"];
NSDate* stageDate = [XMLParser dateFromString:aStage.end];
if([elementName isEqualToString:@"Stages"])
{
return;
}
if([elementName isEqualToString:@"Month"])
{
if (!aMonth.stagesPerMonth || aMonth.stagesPerMonth.count)
{
[appDelegate.stages addObject:aMonth];
}
[aMonth release];
aMonth = nil;
}
if([elementName isEqualToString:@"Stage"])
{
NSTimeInterval interval = [date timeIntervalSinceDate:stageDate];
if (interval < 0)
{
[aMonth.stagesPerMonth addObject:aStage];
}
[aStage release];
aStage = nil;
}
else
{
[aStage setValue:currentElementValue forKey:elementName];
[currentElementValue release];
currentElementValue = nil;
}
}
-(void) parserDidStartDocument:(NSXMLParser *)parser
{
NSLog(@"parserDidStartDocument");
}
-(void) parserDidEndDocument: (NSXMLParser *)parser
{
NSLog(@"parserDidEndDocument");
}
+ (NSDate *)dateFromString:(NSString *)dateString
{
NSDateFormatter *nsDateFormatter = [[NSDateFormatter alloc] init];
[nsDateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm"];
NSDate *date = [nsDateFormatter dateFromString:dateString];
return date;
[nsDateFormatter release];
}
+ (NSString *)stringFromDate:(NSDate *)stringDate
{
NSDateFormatter *stringDateFormatter = [[NSDateFormatter alloc] init];
NSLocale *nlLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"nl_NL"];
[stringDateFormatter setLocale:nlLocale];
[stringDateFormatter setDateFormat:@"EEE', 'dd MMMM yyyy HH:mma"];
NSString *dateString = [stringDateFormatter stringFromDate:stringDate];
return dateString;
[stringDateFormatter release];
}
- (void) dealloc
{
[aStage release];
[aMonth release];
[currentElementValue release];
[super dealloc];
}
@end
DAFAppDelegate.h:
@class RootViewController;
@interface DAFAppDelegate : NSObject <UIApplicationDelegate>
{
UIWindow *window;
UINavigationController *navigationController;
IBOutlet UITabBarController *rootTabController;
RootViewController *rootViewController;
NSMutableArray *stages;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UITabBarController *rootTabController;
@property (nonatomic, retain) IBOutlet UINavigationController *navigationController;
@property (nonatomic, retain) IBOutlet RootViewController *rootViewController;
@property (nonatomic, retain) NSMutableArray *stages;
+ (void) showAlert;
@end
DAFAppDelegate.m:
#import "DAFAppDelegate.h"
#import "RootViewController.h"
#import "XMLParser.h"
@implementation DAFAppDelegate
@synthesize window;
@synthesize navigationController;
@synthesize rootViewController;
@synthesize rootTabController;
@synthesize stages;
+ (void) showAlert
{
UIAlertView *av = [[[UIAlertView alloc] initWithTitle:@"No Connection" message:@"Could not retrieve data" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] autorelease];
[av show];
}
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
NSURL *url = [[NSURL alloc] initWithString:@"http://web.me.com/ijar/Stages.xml"];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithContentsOfURL:url];
//Initialize the delegate.
XMLParser *parser = [[XMLParser alloc] initXMLParser];
//Set delegate
[xmlParser setDelegate:parser];
//Start parsing the XML file.
BOOL success = [xmlParser parse];
if(success)
{
NSLog(@"No Errors");
}
else
{
[DAFAppDelegate showAlert];
NSLog(@"Error Error Error!!!");
}
[window addSubview:[rootTabController view]];
[window makeKeyAndVisible];
}
- (void)dealloc
{
[navigationController release];
[rootViewController release];
[rootTabController release];
[window release];
[stages release];
[super dealloc];
}
@end
RootViewController.h:
@class DAFAppDelegate;
@interface RootViewController : UITableViewController
{
DAFAppDelegate *appDelegate;
}
@end
RootViewController.m:
#import "RootViewController.h"
#import "DAFAppDelegate.h"
#import "DetailViewController.h"
#import "XMLParser.h"
#import "Stage.h"
#import "Month.h"
#import "AgendaCustomCell.h"
@implementation RootViewController
#pragma mark -
#pragma mark View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
appDelegate = (DAFAppDelegate *)[[UIApplication sharedApplication] delegate];
self.title = NSLocalizedString(@"Agenda", @"Master view navigation title");
UIImageView *image=[[UIImageView alloc]initWithFrame:CGRectMake(0,0,45,45)] ;
[image setImage:[UIImage imageNamed:@"topBarIcon.png"]];
[self.navigationController.navigationBar.topItem setTitleView:image];
self.tableView.backgroundColor = [UIColor clearColor];
}
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [appDelegate.stages count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
Month *aMonth = [appDelegate.stages objectAtIndex:section];
return aMonth.name;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
Month *aMonth = [appDelegate.stages objectAtIndex:section];
return [aMonth.stagesPerMonth count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"AgendaCustomCell";
AgendaCustomCell *cell = (AgendaCustomCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
NSArray *topLevelObject = [[NSBundle mainBundle] loadNibNamed:@"AgendaCustomCell" owner:nil options:nil];
for (id currentObject in topLevelObject)
{
if ([currentObject isKindOfClass:[UITableViewCell class]])
{
cell = (AgendaCustomCell *)currentObject;
break;
}
}
}
Month *aMonth = [appDelegate.stages objectAtIndex:indexPath.section];
Stage *aStage = [aMonth.stagesPerMonth objectAtIndex:indexPath.row];
NSString *startDate = [XMLParser stringFromDate:[XMLParser dateFromString:aStage.start]];
NSString *endDate = [XMLParser stringFromDate:[XMLParser dateFromString:aStage.end]];
int endDateLength = endDate.length;
NSString *dateTitle = [NSString stringWithFormat:@"%@ - %@", startDate, [endDate substringFromIndex:endDateLength -7]];
cell.titleLabel.text = aStage.title;
cell.dateLabel.text = dateTitle;
cell.nameLabel.text = aStage.teacher;
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 60;
}
#pragma mark -
#pragma mark Table view selection
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//When a row is selected, create the detail view controller and set its detail item to the item associated with the selected row.
DetailViewController *detailViewController = [[DetailViewController alloc] initWithStyle:UITableViewStyleGrouped];
Month *aMonth = [appDelegate.stages objectAtIndex:indexPath.section];
detailViewController.stage = [aMonth.stagesPerMonth objectAtIndex:indexPath.row];
// Push the detail view controller.
[[self navigationController] pushViewController:detailViewController animated:YES];
[detailViewController release];
}
#pragma mark -
#pragma mark Memory management
- (void)dealloc
{
[appDelegate release];
[super dealloc];
}
@end
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您想在状态栏中使用标准活动指示器,请调用:
就在调用解析器之前。
然后,一旦解析器完成(didEndDocument 方法),调用:
If you want to use the standard activity indicator in the status bar call:
Just before you call the parser.
Then once the parser is complete (the didEndDocument method), call:
我不会为您编写代码,但您可以采取以下一些步骤。
1. 为了获得更好的用户体验,请在开始 xml 解析之前将 RootViewController.view 添加到窗口。
2. 在 RootViewController:viewDidLoad 方法中,创建并显示 UIActivityIndicatorView(“旋转器”)。
3. 解析完成后,调用 RootViewController 上的方法执行 3 件事:
a) 隐藏微调器
b) 加载tableView的数据源(aMonth.stagesPerMonth)
c) 表视图[重新加载数据];
祝你好运。
-麦克风
I'm not going to write the code for you, but here are some steps you could take.
1. For a better UX, add the RootViewController.view to the window before you start the xml parsing.
2. In your RootViewController: viewDidLoad method, create and display a UIActivityIndicatorView (a "spinner").
3. When your parsing is done, call a method on the RootViewController that does 3 things:
a) hides the spinner
b) loads the tableView's data source (aMonth.stagesPerMonth)
c) tableView[reloadData];
Good luck.
-Mike